soc/intel/mtl: Do initial Meteor Lake SoC commit till ramstage

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

BUG=b:224325352
TEST= Build 'util/abuild/abuild -p none -t google/rex -a -c max'.

Signed-off-by: Ravi Sarawadi <ravishankar.sarawadi@intel.com>
Change-Id: Ie746c0bfcf1f315a4ab6f540cc7c4933157551d7
Reviewed-on: https://review.coreboot.org/c/coreboot/+/63364
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Tarun Tuli <taruntuli@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Ravi Sarawadi
2022-05-07 16:37:09 -07:00
committed by Subrata Banik
parent febd3d756b
commit 91ffac8c04
39 changed files with 3095 additions and 7 deletions

View File

@@ -1,36 +1,86 @@
config SOC_INTEL_METEORLAKE config SOC_INTEL_METEORLAKE
bool bool
help
Intel Meteorlake support
if SOC_INTEL_METEORLAKE if SOC_INTEL_METEORLAKE
config CPU_SPECIFIC_OPTIONS config CPU_SPECIFIC_OPTIONS
def_bool y def_bool y
select ACPI_INTEL_HARDWARE_SLEEP_VALUES
select ARCH_X86 select ARCH_X86
select BOOT_DEVICE_SUPPORTS_WRITES select BOOT_DEVICE_SUPPORTS_WRITES
select INTEL_DESCRIPTOR_MODE_CAPABLE
select CACHE_MRC_SETTINGS select CACHE_MRC_SETTINGS
select CPU_INTEL_COMMON select CPU_INTEL_COMMON
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
select CPU_SUPPORTS_INTEL_TME
select CPU_SUPPORTS_PM_TIMER_EMULATION
select DRIVERS_INTEL_USB4_RETIMER
select FSP_COMPRESS_FSP_S_LZ4
select FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW
select FSP_M_XIP select FSP_M_XIP
select FSP_STATUS_GLOBAL_RESET_REQUIRED_3
select GENERIC_GPIO_LIB
select HAVE_FSP_GOP
select INTEL_DESCRIPTOR_MODE_CAPABLE
select HAVE_SMI_HANDLER
select IDT_IN_EVERY_STAGE select IDT_IN_EVERY_STAGE
select INTEL_CAR_NEM select INTEL_CAR_NEM
select INTEL_GMA_ACPI
select INTEL_GMA_ADD_VBT if RUN_FSP_GOP select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
select IOAPIC select IOAPIC
select MICROCODE_BLOB_UNDISCLOSED select INTEL_TME
select USE_INTEL_FSP_MP_INIT
select MRC_SETTINGS_PROTECT select MRC_SETTINGS_PROTECT
select PARALLEL_MP_AP_WORK
select MICROCODE_BLOB_UNDISCLOSED
select PLATFORM_USES_FSP2_3
select PMC_GLOBAL_RESET_ENABLE_LOCK
select SOC_INTEL_COMMON select SOC_INTEL_COMMON
select SOC_INTEL_COMMON_BLOCK select SOC_INTEL_COMMON_BLOCK
select SOC_INTEL_COMMON_BLOCK_CAR select SOC_INTEL_COMMON_BLOCK_CAR
select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG
select SOC_INTEL_COMMON_BLOCK_CPU 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_GSPI_VERSION_2 select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
select SOC_INTEL_COMMON_BLOCK_HDA
select SOC_INTEL_COMMON_BLOCK_HECI1_DISABLE_USING_PMC_IPC if DISABLE_HECI1_AT_PRE_BOOT
select SOC_INTEL_COMMON_BLOCK_IPU
select SOC_INTEL_COMMON_BLOCK_IOE_P2SB
select SOC_INTEL_COMMON_BLOCK_MEMINIT 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_SA
select SOC_INTEL_COMMON_BLOCK_SMM
select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP
select SOC_INTEL_COMMON_BLOCK_TCSS
select SOC_INTEL_COMMON_BLOCK_THERMAL_BEHIND_PMC
select SOC_INTEL_COMMON_BLOCK_USB4
select SOC_INTEL_COMMON_BLOCK_USB4_PCIE
select SOC_INTEL_COMMON_BLOCK_USB4_XHCI
select SOC_INTEL_COMMON_BLOCK_XHCI
select SOC_INTEL_COMMON_BLOCK_XHCI_ELOG
select SOC_INTEL_COMMON_BASECODE
select SOC_INTEL_COMMON_FSP_RESET
select SOC_INTEL_COMMON_PCH_BASE select SOC_INTEL_COMMON_PCH_BASE
select SOC_INTEL_COMMON_RESET select SOC_INTEL_COMMON_RESET
select SOC_INTEL_COMMON_BLOCK_IOC
select SOC_INTEL_CSE_SET_EOP
select SOC_INTEL_MEM_MAPPED_PM_CONFIGURATION
select SSE2 select SSE2
select SUPPORT_CPU_UCODE_IN_CBFS select SUPPORT_CPU_UCODE_IN_CBFS
select TSC_MONOTONIC_TIMER select TSC_MONOTONIC_TIMER
select UDELAY_TSC select UDELAY_TSC
select UDK_202111_BINDING
select DISPLAY_FSP_VERSION_INFO
config MAX_CPUS
int
default 22
config DCACHE_RAM_BASE config DCACHE_RAM_BASE
default 0xfef00000 default 0xfef00000
@@ -58,9 +108,19 @@ config FSP_TEMP_RAM_SIZE
Refer to Platform FSP integration guide document to know Refer to Platform FSP integration guide document to know
the exact FSP requirement for Heap setup. the exact FSP requirement for Heap setup.
config CHIPSET_DEVICETREE
string
default "soc/intel/meteorlake/chipset.cb"
config EXT_BIOS_WIN_BASE
default 0xf8000000
config EXT_BIOS_WIN_SIZE
default 0x2000000
config IFD_CHIPSET config IFD_CHIPSET
string string
default "mtl" default "ifd2"
config IED_REGION_SIZE config IED_REGION_SIZE
hex hex
@@ -70,6 +130,47 @@ config HEAP_SIZE
hex hex
default 0x10000 default 0x10000
# Intel recommends reserving the following resources per PCIe TBT root port,
# from ADL BIOS Spec (doc #627270) Revision 0.6.0 Section 7.2.5.1.5
# - 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
config MAX_ROOT_PORTS
int
default 12
config MAX_PCIE_CLOCK_SRC
int
default 9
config SMM_TSEG_SIZE
hex
default 0x800000
config SMM_RESERVED_SIZE
hex
default 0x200000
config PCR_BASE_ADDRESS config PCR_BASE_ADDRESS
hex hex
default 0xe0000000 default 0xe0000000
@@ -106,11 +207,23 @@ config SOC_INTEL_UART_DEV_MAX
int int
default 3 default 3
config SOC_INTEL_USB2_DEV_MAX
int
default 10
config SOC_INTEL_USB3_DEV_MAX
int
default 2
config CONSOLE_UART_BASE_ADDRESS config CONSOLE_UART_BASE_ADDRESS
hex hex
default 0xfe03e000 default 0xfe02c000
depends on INTEL_LPSS_UART_FOR_CONSOLE depends on INTEL_LPSS_UART_FOR_CONSOLE
config VBT_DATA_SIZE_KB
int
default 9
# Clock divider parameters for 115200 baud rate # Clock divider parameters for 115200 baud rate
# Baudrate = (UART source clock * M) /(N *16) # Baudrate = (UART source clock * M) /(N *16)
# MTL UART source clock: 120MHz # MTL UART source clock: 120MHz
@@ -123,6 +236,7 @@ config SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL
default 0x7fff default 0x7fff
config VBOOT config VBOOT
select VBOOT_SEPARATE_VERSTAGE
select VBOOT_MUST_REQUEST_DISPLAY select VBOOT_MUST_REQUEST_DISPLAY
select VBOOT_STARTS_IN_BOOTBLOCK select VBOOT_STARTS_IN_BOOTBLOCK
select VBOOT_VBNV_CMOS select VBOOT_VBNV_CMOS
@@ -141,7 +255,7 @@ config CBFS_SIZE
config PRERAM_CBMEM_CONSOLE_SIZE config PRERAM_CBMEM_CONSOLE_SIZE
hex hex
default 0x2000 default 0x1400
config FSP_HEADER_PATH config FSP_HEADER_PATH
string "Location of FSP headers" string "Location of FSP headers"
@@ -156,7 +270,7 @@ config SOC_INTEL_METEORLAKE_DEBUG_CONSENT
int "Debug Consent for MTL" int "Debug Consent for MTL"
# USB DBC is more common for developers so make this default to 3 if # USB DBC is more common for developers so make this default to 3 if
# SOC_INTEL_DEBUG_CONSENT=y # SOC_INTEL_DEBUG_CONSENT=y
default 3 if SOC_INTEL_DEBUG_CONSENT default 5 if SOC_INTEL_DEBUG_CONSENT
default 0 default 0
help help
This is to control debug interface on SOC. This is to control debug interface on SOC.
@@ -180,4 +294,8 @@ config MRC_CHANNEL_WIDTH
int int
default 16 default 16
config SOC_INTEL_GFX_FRAMEBUFFER_OFFSET
hex
default 0x800000
endif endif

View File

@@ -4,18 +4,55 @@ subdirs-y += romstage
subdirs-y += ../../../cpu/intel/microcode subdirs-y += ../../../cpu/intel/microcode
subdirs-y += ../../../cpu/intel/turbo 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
bootblock-y += bootblock/bootblock.c bootblock-y += bootblock/bootblock.c
bootblock-y += bootblock/ioe_die.c bootblock-y += bootblock/ioe_die.c
bootblock-y += bootblock/report_platform.c bootblock-y += bootblock/report_platform.c
bootblock-y += bootblock/soc_die.c bootblock-y += bootblock/soc_die.c
bootblock-y += espi.c bootblock-y += espi.c
bootblock-y += p2sb.c bootblock-y += p2sb.c
bootblock-y += soc_info.c
romstage-y += espi.c romstage-y += espi.c
romstage-y += meminit.c romstage-y += meminit.c
romstage-y += pcie_rp.c
romstage-y += reset.c romstage-y += reset.c
romstage-y += soc_info.c
ramstage-y += acpi.c
ramstage-y += chip.c
ramstage-y += cpu.c
ramstage-y += elog.c
ramstage-y += espi.c
ramstage-y += finalize.c
ramstage-y += fsp_params.c
ramstage-y += lockdown.c
ramstage-y += me.c
ramstage-y += p2sb.c
ramstage-y += pcie_rp.c
ramstage-y += pmc.c
ramstage-y += reset.c
ramstage-y += retimer.c
ramstage-y += soundwire.c
ramstage-y += systemagent.c
ramstage-y += tcss.c
ramstage-y += xhci.c
ramstage-y += soc_info.c
smm-y += elog.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/meteorlake CPPFLAGS_common += -I$(src)/soc/intel/meteorlake
CPPFLAGS_common += -I$(src)/soc/intel/meteorlake/include CPPFLAGS_common += -I$(src)/soc/intel/meteorlake/include
CFLAGS_common += -fshort-wchar
endif endif

View File

@@ -0,0 +1,257 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi.h>
#include <acpi/acpi_gnvs.h>
#include <acpi/acpigen.h>
#include <device/mmio.h>
#include <arch/smp/mpspec.h>
#include <console/console.h>
#include <device/device.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 <string.h>
#include <types.h>
/*
* 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
};
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),
},
};
static int cstate_set_non_s0ix[] = {
C_STATE_C1,
C_STATE_C6_LONG_LAT,
C_STATE_C7S_LONG_LAT
};
static int cstate_set_s0ix[] = {
C_STATE_C1,
C_STATE_C7S_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))];
int *set;
int i;
config_t *config = config_of_soc();
int is_s0ix_enable = config->s0ix_enable;
if (is_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;
}
return map;
}
void soc_power_states_generation(int core_id, int cores_per_package)
{
config_t *config = config_of_soc();
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();
fadt->pm_tmr_blk = pmbase + PM1_TMR;
fadt->pm_tmr_len = 4;
fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
fadt->x_pm_tmr_blk.addrh = 0x0;
if (config->s0ix_enable)
fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
}
uint32_t soc_read_sci_irq_select(void)
{
return read32((void *)soc_read_pmc_base() + IRQ_REG);
}
static unsigned long soc_fill_dmar(unsigned long current)
{
unsigned long tmp;
const struct device *const igfx_dev = pcidev_path_on_root(PCI_DEVFN_IGD);
const uint64_t gfxvtbar = MCHBAR64(GFXVTBAR) & VTBAR_MASK;
const bool gfxvten = MCHBAR32(GFXVTBAR) & VTBAR_ENABLED;
printk(BIOS_DEBUG, "%s - gfxvtbar:0x%llx 0x%x\n",
__func__, gfxvtbar, MCHBAR32(GFXVTBAR));
if (is_dev_enabled(igfx_dev) && gfxvtbar && gfxvten) {
tmp = current;
current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IGD, 0);
acpi_dmar_drhd_fixup(tmp, current);
}
tmp = current;
current += acpi_create_dmar_drhd(current,
DRHD_INCLUDE_PCI_ALL, 0, VTVC0_BASE_ADDRESS);
current += acpi_create_dmar_ds_ioapic(current,
2, 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 (is_dev_enabled(igfx_dev) && gfxvtbar && gfxvten) {
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);
}
tmp = current;
current += acpi_create_dmar_satc(current, ATC_REQUIRED, 0);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IGD, 0);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IPU, 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) & VTBAR_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();
/* Enable DPTF based on mainboard configuration */
gnvs->dpte = config->dptf_enable;
/* Set USB2/USB3 wake enable bitmaps. */
gnvs->u2we = config->usb2_wake_enable_bitmap;
gnvs->u3we = config->usb3_wake_enable_bitmap;
}
int soc_madt_sci_irq_polarity(int sci)
{
return MP_IRQ_POLARITY_HIGH;
}

View File

@@ -0,0 +1,185 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/device.h>
#include <device/pci.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <intelblocks/acpi.h>
#include <intelblocks/cfg.h>
#include <intelblocks/gpio.h>
#include <intelblocks/itss.h>
#include <intelblocks/pcie_rp.h>
#include <intelblocks/systemagent.h>
#include <intelblocks/xdci.h>
#include <soc/intel/common/vbt.h>
#include <soc/itss.h>
#include <soc/p2sb.h>
#include <soc/pci_devs.h>
#include <soc/pcie.h>
#include <soc/ramstage.h>
#include <soc/soc_chip.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";
case 8: return "HS09";
case 9: return "HS10";
}
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_DEBUG, "dev->path.type=%x\n", dev->path.usb.port_type);
return NULL;
}
if (dev->path.type != DEVICE_PATH_PCI) {
printk(BIOS_DEBUG, "dev->path.type=%x\n", dev->path.type);
return NULL;
}
switch (dev->path.pci.devfn) {
case PCI_DEVFN_ROOT: return "MCHC";
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_IPU: return "IPU0";
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_SATA: return "SATA";
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_DEBUG, "dev->path.devfn=%x\n", dev->path.pci.devfn);
return NULL;
}
#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);
}
void soc_init_pre_device(void *chip_info)
{
/* 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());
}
static struct device_operations pci_domain_ops = {
.read_resources = &pci_domain_read_resources,
.set_resources = &pci_domain_set_resources,
.scan_bus = &pci_domain_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,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_fill_ssdt = generate_cpu_entries,
#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_IOE_P2SB)
dev->ops = &ioe_p2sb_ops;
else if (dev->path.type == DEVICE_PATH_GPIO)
block_gpio_enable(dev);
}
struct chip_operations soc_intel_meteorlake_ops = {
CHIP_NAME("Intel Meteorlake")
.enable_dev = &soc_enable,
.init = &soc_init_pre_device,
};

View File

@@ -0,0 +1,161 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cpu.h>
#include <console/console.h>
#include <device/pci.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/turbo.h>
#include <cpu/intel/common/common.h>
#include <fsp/api.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/mp_init.h>
#include <intelblocks/msr.h>
#include <intelblocks/acpi.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/soc_chip.h>
#include <soc/soc_info.h>
#include <assert.h>
bool cpu_soc_is_in_untrusted_mode(void)
{
msr_t msr;
msr = rdmsr(MSR_BIOS_DONE);
return !!(msr.lo & ENABLE_IA_UNTRUSTED);
}
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 |= (1 << 0); /* Fast String enable */
msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
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 = 1 << 4;
msr.hi = 0;
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
/* Enable PROCHOT */
msr = rdmsr(MSR_POWER_CTL);
msr.lo |= (1 << 0); /* Enable Bi-directional PROCHOT as an input*/
msr.lo |= (1 << 23); /* Lock it */
wrmsr(MSR_POWER_CTL, msr);
}
enum core_type get_soc_cpu_type(void)
{
if (cpu_is_hybrid_supported())
return cpu_get_cpu_type();
else
return CPUID_CORE_TYPE_INTEL_CORE;
}
void soc_get_scaling_factor(u16 *big_core_scal_factor, u16 *small_core_scal_factor)
{
*big_core_scal_factor = 127;
*small_core_scal_factor = 100;
}
bool soc_is_nominal_freq_supported(void)
{
return true;
}
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
/* Clear out pending MCEs */
/* TODO(adurbin): This should only be done on a cold boot. Also, some
* of these banks are core vs package scope. For now every CPU clears
* every bank. */
mca_configure();
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);
/* Enable Turbo */
enable_turbo();
}
static void per_cpu_smm_trigger(void)
{
/* Relocate the SMM handler. */
smm_relocate();
}
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 = soc_fsp_load,
.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 soc_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();
}

View File

@@ -0,0 +1,220 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci_ops.h>
#include <elog.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/xhci.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/soc_info.h>
#include <stdint.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 },
{ PCI_DEVFN_PCIE11, ELOG_WAKE_SOURCE_PME_PCIE11 },
{ PCI_DEVFN_PCIE12, ELOG_WAKE_SOURCE_PME_PCIE12 },
};
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_SATA, ELOG_WAKE_SOURCE_PME_SATA },
{ 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 & TCO_STS_SECOND_TO)
elog_add_event(ELOG_TYPE_TCO_RESET);
/* Power Button Override */
if (ps->pm1_sts & PRBTNOR_STS)
elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
/* RTC reset */
if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
elog_add_event(ELOG_TYPE_RTC_RESET);
/* Host Reset Status */
if (ps->gen_pmcon_a & HOST_RST_STS)
elog_add_event(ELOG_TYPE_SYSTEM_RESET);
/* ACPI Wake Event */
if (ps->prev_sleep_state != ACPI_S0)
elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
}
static void pch_log_state(void *unused)
{
struct chipset_power_state *ps = pmc_get_power_state();
if (!ps) {
printk(BIOS_ERR, "chipset_power_state not found!\n");
return;
}
/* Power and Reset */
pch_log_power_and_resets(ps);
/* Wake Sources */
if (ps->prev_sleep_state > ACPI_S0)
pch_log_wake_source(ps);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
void elog_gsmi_cb_platform_log_wake_source(void)
{
struct chipset_power_state ps;
pmc_fill_pm_reg_info(&ps);
pch_log_wake_source(&ps);
}

View File

@@ -0,0 +1,88 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/io.h>
#include <device/mmio.h>
#include <bootstate.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <delay.h>
#include <device/pci.h>
#include <intelblocks/cse.h>
#include <intelblocks/gpio.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 <spi-generic.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 <timer.h>
static void pch_handle_sideband(config_t *config)
{
}
static void pch_finalize(void)
{
config_t *config = config_of_soc();
/* TCO Lock down */
tco_lockdown();
/* TODO: Add Thermal Configuration */
pch_handle_sideband(config);
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 soc_finalize(void *unused)
{
printk(BIOS_DEBUG, "Finalizing chipset.\n");
pch_finalize();
apm_control(APM_CNT_FINALIZE);
tbt_finalize();
sa_finalize();
heci_set_to_d0i3();
if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
heci1_disable();
/* Indicate finalize step with post code */
post_code(POST_OS_BOOT);
}
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL);
/*
* The purpose of this change is to accommodate more time to push out sending
* CSE EOP messages at post.
*/
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, soc_finalize, NULL);

View File

@@ -0,0 +1,486 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <cbfs.h>
#include <console/console.h>
#include <cpu/intel/cpu_ids.h>
#include <device/device.h>
#include <device/pci.h>
#include <fsp/api.h>
#include <fsp/ppi/mp_service_ppi.h>
#include <fsp/util.h>
#include <intelblocks/cse.h>
#include <intelblocks/lpss.h>
#include <intelblocks/xdci.h>
#include <intelpch/lockdown.h>
#include <intelblocks/tcss.h>
#include <security/vboot/vboot_common.h>
#include <soc/gpio_soc_defs.h>
#include <soc/intel/common/vbt.h>
#include <soc/pci_devs.h>
#include <soc/pcie.h>
#include <soc/ramstage.h>
#include <soc/soc_chip.h>
#include <soc/soc_info.h>
#include <soc/cpu.h>
#include <string.h>
/* THC assignment definition */
#define THC_NONE 0
#define THC_0 1
#define THC_1 2
/* SATA DEVSLP idle timeout default values */
#define DEF_DMVAL 15
#define DEF_DITOVAL 625
/*
* ME End of Post configuration
* 0 - Disable EOP.
* 1 - Send in PEI (Applicable for FSP in API mode)
* 2 - Send in DXE (Not applicable for FSP in API mode)
*/
enum fsp_end_of_post {
EOP_DISABLE = 0,
EOP_PEI = 1,
EOP_DXE = 2,
};
static const pci_devfn_t i2c_dev[] = {
PCI_DEVFN_I2C0,
PCI_DEVFN_I2C1,
PCI_DEVFN_I2C2,
PCI_DEVFN_I2C3,
PCI_DEVFN_I2C4,
PCI_DEVFN_I2C5,
};
static const pci_devfn_t gspi_dev[] = {
PCI_DEVFN_GSPI0,
PCI_DEVFN_GSPI1,
};
static const pci_devfn_t uart_dev[] = {
PCI_DEVFN_UART0,
PCI_DEVFN_UART1,
PCI_DEVFN_UART2
};
/*
* Chip config parameter PcieRpL1Substates uses (UPD value + 1)
* because UPD value of 0 for PcieRpL1Substates means disabled for FSP.
* In order to ensure that mainboard setting does not disable L1 substates
* incorrectly, chip config parameter values are offset by 1 with 0 meaning
* use FSP UPD default. get_l1_substate_control() ensures that the right UPD
* value is set in fsp_params.
* 0: Use FSP UPD default
* 1: Disable L1 substates
* 2: Use L1.1
* 3: Use L1.2 (FSP UPD default)
*/
static int get_l1_substate_control(enum L1_substates_control ctl)
{
if ((ctl > L1_SS_L1_2) || (ctl == L1_SS_FSP_DEFAULT))
ctl = L1_SS_L1_2;
return ctl - 1;
}
__weak void mainboard_update_soc_chip_config(struct soc_intel_meteorlake_config *config)
{
/* Override settings per board. */
}
static void fill_fsps_lpss_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
int max_port, i;
max_port = get_max_i2c_port();
for (i = 0; i < max_port; i++) {
s_cfg->SerialIoI2cMode[i] = is_devfn_enabled(i2c_dev[i]) ?
config->serial_io_i2c_mode[i] : 0;
}
max_port = get_max_gspi_port();
for (i = 0; i < max_port; i++) {
s_cfg->SerialIoSpiCsMode[i] = config->serial_io_gspi_cs_mode[i];
s_cfg->SerialIoSpiCsState[i] = config->serial_io_gspi_cs_state[i];
s_cfg->SerialIoSpiMode[i] = is_devfn_enabled(gspi_dev[i]) ?
config->serial_io_gspi_mode[i] : 0;
}
max_port = get_max_uart_port();
for (i = 0; i < max_port; i++) {
s_cfg->SerialIoUartMode[i] = is_devfn_enabled(uart_dev[i]) ?
config->serial_io_uart_mode[i] : 0;
}
}
static void fill_fsps_cpu_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
const struct microcode *microcode_file;
size_t microcode_len;
/* Locate microcode and pass to FSP-S for 2nd microcode loading */
microcode_file = cbfs_map("cpu_microcode_blob.bin", &microcode_len);
if ((microcode_file != NULL) && (microcode_len != 0)) {
/* Update CPU Microcode patch base address/size */
s_cfg->MicrocodeRegionBase = (uint32_t)microcode_file;
s_cfg->MicrocodeRegionSize = (uint32_t)microcode_len;
}
/* Use coreboot MP PPI services if Kconfig is enabled */
if (CONFIG(USE_INTEL_FSP_TO_CALL_COREBOOT_PUBLISH_MP_PPI))
s_cfg->CpuMpPpi = (uintptr_t) mp_fill_ppi_services_data();
}
static void fill_fsps_igd_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* Load VBT before devicetree-specific config. */
s_cfg->GraphicsConfigPtr = (uintptr_t)vbt_get();
/* Check if IGD is present and fill Graphics init param accordingly */
s_cfg->PeiGraphicsPeimInit = CONFIG(RUN_FSP_GOP) && is_devfn_enabled(PCI_DEVFN_IGD);
s_cfg->LidStatus = CONFIG(RUN_FSP_GOP);
}
static void fill_fsps_tcss_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
const struct device *tcss_port_arr[] = {
DEV_PTR(tcss_usb3_port1),
DEV_PTR(tcss_usb3_port2),
DEV_PTR(tcss_usb3_port3),
DEV_PTR(tcss_usb3_port4),
};
s_cfg->TcssAuxOri = config->tcss_aux_ori;
/* Explicitly clear this field to avoid using defaults */
memset(s_cfg->IomTypeCPortPadCfg, 0, sizeof(s_cfg->IomTypeCPortPadCfg));
/* D3Hot and D3Cold for TCSS */
s_cfg->D3HotEnable = !config->tcss_d3_hot_disable;
s_cfg->D3ColdEnable = !config->tcss_d3_cold_disable;
s_cfg->UsbTcPortEn = 0;
for (int i = 0; i < MAX_TYPE_C_PORTS; i++) {
if (is_dev_enabled(tcss_port_arr[i]))
s_cfg->UsbTcPortEn |= BIT(i);
}
}
static void fill_fsps_chipset_lockdown_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* Chipset Lockdown */
const bool lockdown_by_fsp = get_lockdown_config() == CHIPSET_LOCKDOWN_FSP;
s_cfg->PchLockDownGlobalSmi = lockdown_by_fsp;
s_cfg->PchLockDownBiosInterface = lockdown_by_fsp;
s_cfg->PchUnlockGpioPads = !lockdown_by_fsp;
s_cfg->RtcMemoryLock = lockdown_by_fsp;
s_cfg->SkipPamLock = !lockdown_by_fsp;
/* coreboot will send EOP before loading payload */
s_cfg->EndOfPostMessage = EOP_DISABLE;
}
static void fill_fsps_xhci_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
int i, max_port;
max_port = get_max_usb20_port();
for (i = 0; i < max_port; i++) {
s_cfg->PortUsb20Enable[i] = config->usb2_ports[i].enable;
s_cfg->Usb2PhyPetxiset[i] = config->usb2_ports[i].pre_emp_bias;
s_cfg->Usb2PhyTxiset[i] = config->usb2_ports[i].tx_bias;
s_cfg->Usb2PhyPredeemp[i] = config->usb2_ports[i].tx_emp_enable;
s_cfg->Usb2PhyPehalfbit[i] = config->usb2_ports[i].pre_emp_bit;
if (config->usb2_ports[i].enable)
s_cfg->Usb2OverCurrentPin[i] = config->usb2_ports[i].ocpin;
else
s_cfg->Usb2OverCurrentPin[i] = OC_SKIP;
}
max_port = get_max_usb30_port();
for (i = 0; i < max_port; i++) {
s_cfg->PortUsb30Enable[i] = config->usb3_ports[i].enable;
if (config->usb3_ports[i].enable)
s_cfg->Usb3OverCurrentPin[i] = config->usb3_ports[i].ocpin;
else
s_cfg->Usb3OverCurrentPin[i] = OC_SKIP;
if (config->usb3_ports[i].tx_de_emp) {
s_cfg->Usb3HsioTxDeEmphEnable[i] = 1;
s_cfg->Usb3HsioTxDeEmph[i] = config->usb3_ports[i].tx_de_emp;
}
if (config->usb3_ports[i].tx_downscale_amp) {
s_cfg->Usb3HsioTxDownscaleAmpEnable[i] = 1;
s_cfg->Usb3HsioTxDownscaleAmp[i] =
config->usb3_ports[i].tx_downscale_amp;
}
}
max_port = get_max_tcss_port();
for (i = 0; i < max_port; i++) {
s_cfg->PortUsb30Enable[i] = config->tcss_ports[i].enable;
if (config->tcss_ports[i].enable)
s_cfg->CpuUsb3OverCurrentPin[i] = config->tcss_ports[i].ocpin;
}
}
static void fill_fsps_xdci_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
s_cfg->XdciEnable = xdci_can_enable(PCI_DEVFN_USBOTG);
}
static void fill_fsps_sata_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* SATA */
s_cfg->SataEnable = is_devfn_enabled(PCI_DEVFN_SATA);
if (s_cfg->SataEnable) {
s_cfg->SataMode = config->sata_mode;
s_cfg->SataSalpSupport = config->sata_salp_support;
memcpy(s_cfg->SataPortsEnable, config->sata_ports_enable,
sizeof(s_cfg->SataPortsEnable));
memcpy(s_cfg->SataPortsDevSlp, config->sata_ports_dev_slp,
sizeof(s_cfg->SataPortsDevSlp));
}
/*
* Power Optimizer for SATA.
* SataPwrOptimizeDisable is default to 0.
* Boards not needing the optimizers explicitly disables them by setting
* these disable variables to 1 in devicetree overrides.
*/
s_cfg->SataPwrOptEnable = !(config->sata_pwr_optimize_disable);
/*
* Enable DEVSLP Idle Timeout settings DmVal and DitoVal.
* SataPortsDmVal is the DITO multiplier. Default is 15.
* SataPortsDitoVal is the DEVSLP Idle Timeout (DITO), Default is 625ms.
* The default values can be changed from devicetree.
*/
for (size_t i = 0; i < ARRAY_SIZE(config->sata_ports_enable_dito_config); i++) {
if (config->sata_ports_enable_dito_config[i]) {
s_cfg->SataPortsDmVal[i] = config->sata_ports_dm_val[i];
s_cfg->SataPortsDitoVal[i] = config->sata_ports_dito_val[i];
}
}
}
static void fill_fsps_thermal_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* Enable TCPU for processor thermal control */
s_cfg->Device4Enable = is_devfn_enabled(PCI_DEVFN_DPTF);
/* Set TccActivationOffset */
s_cfg->TccActivationOffset = config->tcc_offset;
}
static void fill_fsps_lan_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* LAN */
s_cfg->PchLanEnable = is_devfn_enabled(PCI_DEVFN_GBE);
}
static void fill_fsps_cnvi_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* CNVi */
s_cfg->CnviMode = is_devfn_enabled(PCI_DEVFN_CNVI_WIFI);
s_cfg->CnviBtCore = config->cnvi_bt_core;
s_cfg->CnviBtAudioOffload = config->cnvi_bt_audio_offload;
/* Assert if CNVi BT is enabled without CNVi being enabled. */
assert(s_cfg->CnviMode || !s_cfg->CnviBtCore);
/* Assert if CNVi BT offload is enabled without CNVi BT being enabled. */
assert(s_cfg->CnviBtCore || !s_cfg->CnviBtAudioOffload);
}
static void fill_fsps_vmd_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* VMD */
s_cfg->VmdEnable = is_devfn_enabled(PCI_DEVFN_VMD);
}
static void fill_fsps_tbt_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
int max_port = get_max_tbt_pcie_port();
memset(s_cfg->ITbtPcieRootPortEn, 0, sizeof(s_cfg->ITbtPcieRootPortEn));
for (int i = 0; i < max_port; i++)
s_cfg->ITbtPcieRootPortEn[i] = !(config->tbt_pcie_port_disable[i]);
}
static void fill_fsps_8254_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* Legacy 8254 timer support */
s_cfg->Enable8254ClockGating = !CONFIG(USE_LEGACY_8254_TIMER);
s_cfg->Enable8254ClockGatingOnS3 = !CONFIG(USE_LEGACY_8254_TIMER);
}
static void fill_fsps_storage_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
/* Enable Hybrid storage auto detection */
if (CONFIG(SOC_INTEL_CSE_LITE_SKU) && cse_is_hfs3_fw_sku_lite()
&& vboot_recovery_mode_enabled() && !cse_is_hfs1_com_normal()) {
/*
* CSE Lite SKU does not support hybrid storage dynamic configuration
* in CSE RO boot, and FSP does not allow to send the strap override
* HECI commands if CSE is not in normal mode; hence, hybrid storage
* mode is disabled on CSE RO boot in recovery boot mode.
*/
printk(BIOS_INFO, "cse_lite: CSE RO boot. HybridStorageMode disabled\n");
s_cfg->HybridStorageMode = 0;
} else {
s_cfg->HybridStorageMode = config->hybrid_storage_mode;
}
}
static void fill_fsps_pcie_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
int max_port = get_max_pcie_port();
uint32_t enable_mask = pcie_rp_enable_mask(get_pcie_rp_table());
for (int i = 0; i < max_port; i++) {
if (!(enable_mask & BIT(i)))
continue;
const struct pcie_rp_config *rp_cfg = &config->pcie_rp[i];
s_cfg->PcieRpL1Substates[i] =
get_l1_substate_control(rp_cfg->PcieRpL1Substates);
s_cfg->PcieRpLtrEnable[i] = !!(rp_cfg->flags & PCIE_RP_LTR);
s_cfg->PcieRpAdvancedErrorReporting[i] = !!(rp_cfg->flags & PCIE_RP_AER);
s_cfg->PcieRpHotPlug[i] = !!(rp_cfg->flags & PCIE_RP_HOTPLUG);
s_cfg->PcieRpClkReqDetect[i] = !!(rp_cfg->flags & PCIE_RP_CLK_REQ_DETECT);
}
}
static void fill_fsps_misc_power_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
s_cfg->Hwp = 1;
s_cfg->Cx = 1;
s_cfg->PsOnEnable = 1;
/* Enable the energy efficient turbo mode */
s_cfg->EnergyEfficientTurbo = 1;
/*
* UPDATEME: This is WA for HFPGA
* Disable Pch Pm Energy Report
* Energy Report is disabled to enhance boottime with HFPGA.
*/
s_cfg->PchPmDisableEnergyReport = 1;
s_cfg->PmcLpmS0ixSubStateEnableMask = get_supported_lpm_mask();
}
static void fill_fsps_ufs_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
s_cfg->UfsEnable[0] = is_devfn_enabled(PCI_DEVFN_UFS);
}
static void fill_fsps_ai_params(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config)
{
s_cfg->GnaEnable = is_devfn_enabled(PCI_DEVFN_GNA);
}
static void arch_silicon_init_params(FSPS_ARCH_UPD *s_arch_cfg)
{
/* UPDATEME: Disable for VP
* EnableMultiPhaseSiliconInit for running MultiPhaseSiInit
*/
s_arch_cfg->EnableMultiPhaseSiliconInit = 0;
}
static void soc_silicon_init_params(FSP_S_CONFIG *s_cfg,
struct soc_intel_meteorlake_config *config)
{
/* Override settings per board if required. */
mainboard_update_soc_chip_config(config);
const void (*fill_fsps_params[])(FSP_S_CONFIG *s_cfg,
const struct soc_intel_meteorlake_config *config) = {
fill_fsps_lpss_params,
fill_fsps_cpu_params,
fill_fsps_igd_params,
fill_fsps_tcss_params,
fill_fsps_chipset_lockdown_params,
fill_fsps_xhci_params,
fill_fsps_xdci_params,
fill_fsps_sata_params,
fill_fsps_thermal_params,
fill_fsps_lan_params,
fill_fsps_cnvi_params,
fill_fsps_vmd_params,
fill_fsps_tbt_params,
fill_fsps_8254_params,
fill_fsps_storage_params,
fill_fsps_pcie_params,
fill_fsps_misc_power_params,
fill_fsps_ufs_params,
fill_fsps_ai_params,
};
for (size_t i = 0; i < ARRAY_SIZE(fill_fsps_params); i++)
fill_fsps_params[i](s_cfg, config);
}
/* UPD parameters to be initialized before SiliconInit */
void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
{
struct soc_intel_meteorlake_config *config;
FSP_S_CONFIG *s_cfg = &supd->FspsConfig;
FSPS_ARCH_UPD *s_arch_cfg = &supd->FspsArchUpd;
config = config_of_soc();
arch_silicon_init_params(s_arch_cfg);
soc_silicon_init_params(s_cfg, config);
mainboard_silicon_init_params(s_cfg);
}
/*
* Callbacks for SoC/Mainboard specific overrides for FspMultiPhaseSiInit
* This platform supports below MultiPhaseSIInit Phase(s):
* Phase | FSP return point | Purpose
* ------- + ------------------------------------------------ + -------------------------------
* 1 | After TCSS initialization completed | for TCSS specific init
*/
void platform_fsp_multi_phase_init_cb(uint32_t phase_index)
{
switch (phase_index) {
case 1:
/* TCSS specific initialization here */
printk(BIOS_DEBUG, "FSP MultiPhaseSiInit %s/%s called\n",
__FILE__, __func__);
if (CONFIG(SOC_INTEL_COMMON_BLOCK_TCSS)) {
const config_t *config = config_of_soc();
tcss_configure(config->typec_aux_bias_pads);
}
break;
default:
break;
}
}
/* Mainboard GPIO Configuration */
__weak void mainboard_silicon_init_params(FSP_S_CONFIG *s_cfg)
{
printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
}

View File

@@ -0,0 +1,15 @@
/* 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;
}
return -1;
}

View File

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

View File

@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_METEORLAKE_CPU_H_
#define _SOC_METEORLAKE_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 /* _SOC_METEORLAKE_CPU_H_ */

View File

@@ -61,6 +61,14 @@
#define P2SB_BAR CONFIG_PCR_BASE_ADDRESS #define P2SB_BAR CONFIG_PCR_BASE_ADDRESS
#define P2SB_SIZE (16 * MiB) #define P2SB_SIZE (16 * MiB)
#define IOE_PCR_ABOVE_4G_BASE_ADDR 0x3fff0000000
#define IOE_P2SB_BAR IOE_PCR_ABOVE_4G_BASE_ADDR
#define IOE_P2SB_SIZE (256 * MiB)
#define IOM_BASE_ADDR 0x3fff0aa0000
#define IOM_BASE_SIZE 0x1600
#define IOM_BASE_ADDR_MAX 0x3fff0aa15ff
/* /*
* I/O port address space * I/O port address space
*/ */

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_IRQ_H_
#define _SOC_IRQ_H_
#define GPIO_IRQ14 14
#define GPIO_IRQ15 15
#define PCH_IRQ10 10
#define PCH_IRQ11 11
#define LPSS_UART0_IRQ 16
#define LPSS_UART1_IRQ 17
#define LPSS_UART2_IRQ 31
#endif

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SOC_INTEL_MTL_ITSS_H
#define SOC_INTEL_MTL_ITSS_H
#define GPIO_IRQ_START 50
#define GPIO_IRQ_END ITSS_MAX_IRQ
#define ITSS_MAX_IRQ 119
#define IRQS_PER_IPC 32
#define NUM_IPC_REGS ((ITSS_MAX_IRQ + IRQS_PER_IPC - 1)/IRQS_PER_IPC)
#endif /* SOC_INTEL_ADL_ITSS_H */

View File

@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _METEORLAKE_ME_H_
#define _METEORLAKE_ME_H_
#include <stdint.h>
/* ME Host Firmware Status register 1 */
union me_hfsts1 {
u32 data;
struct {
u32 working_state: 4;
u32 mfg_mode: 1;
u32 fpt_bad: 1;
u32 operation_state: 3;
u32 fw_init_complete: 1;
u32 ft_bup_ld_flr: 1;
u32 update_in_progress: 1;
u32 error_code: 4;
u32 operation_mode: 4;
u32 reset_count: 4;
u32 boot_options_present: 1;
u32 invoke_enhance_dbg_mode: 1;
u32 bist_test_state: 1;
u32 bist_reset_request: 1;
u32 current_power_source: 2;
u32 reserved: 1;
u32 d0i3_support_valid: 1;
} __packed fields;
};
/* ME Host Firmware Status Register 3 */
union me_hfsts3 {
u32 data;
struct {
u32 reserved_0: 4;
u32 fw_sku: 3;
u32 reserved_7: 2;
u32 reserved_9: 2;
u32 resered_11: 3;
u32 resered_14: 16;
u32 reserved_30: 2;
} __packed fields;
};
#endif

View File

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

View File

@@ -8,4 +8,6 @@
#define PCH_P2SB_EPMASK0 0x220 #define PCH_P2SB_EPMASK0 0x220
extern struct device_operations ioe_p2sb_ops;
#endif #endif

View File

@@ -8,7 +8,7 @@
#define _PCI_DEVFN(slot, func) PCI_DEVFN(PCI_DEV_SLOT_ ## slot, func) #define _PCI_DEVFN(slot, func) PCI_DEVFN(PCI_DEV_SLOT_ ## slot, func)
#if !defined(__SIMPLE_DEVICE__) #if !defined(__SIMPLE_DEVICE__)
#include <device/device.h> #include <device/device.h>
#define _PCI_DEV(slot, func) pcidev_path_on_root(_PCI_DEVFN(slot, func), __func__) #define _PCI_DEV(slot, func) pcidev_path_on_root_debug(_PCI_DEVFN(slot, func), __func__)
#else #else
#define _PCI_DEV(slot, func) PCI_DEV(0, PCI_DEV_SLOT_ ## slot, func) #define _PCI_DEV(slot, func) PCI_DEV(0, PCI_DEV_SLOT_ ## slot, func)
#endif #endif

View File

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

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_RAMSTAGE_H_
#define _SOC_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_meteorlake_config *config);
void soc_init_pre_device(void *chip_info);
#endif

View File

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

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
uint8_t get_max_usb20_port(void);
uint8_t get_max_usb30_port(void);
uint8_t get_max_tcss_port(void);
uint8_t get_max_tbt_pcie_port(void);
uint8_t get_max_pcie_port(void);
uint8_t get_max_pcie_clock(void);
uint8_t get_max_uart_port(void);
uint8_t get_max_i2c_port(void);
uint8_t get_max_gspi_port(void);

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _SOC_TCSS_H_
#define _SOC_TCSS_H_
/* Thunderbolt firmware IMR status */
#define IOM_CSME_IMR_TBT_STATUS 0x14
#define TBT_VALID_AUTHENTICATION (1 << 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)
#endif /* _SOC_TCSS_H_ */

View File

@@ -0,0 +1,154 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_USB_H_
#define _SOC_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;
};
/* 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, \
}
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

View File

@@ -0,0 +1,60 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/mmio.h>
#include <intelblocks/cfg.h>
#include <intelpch/lockdown.h>
#include <soc/pm.h>
#include <stdint.h>
static void pmc_lock_pmsync(void)
{
uint8_t *pmcbase;
uint32_t pmsyncreg;
pmcbase = pmc_mmio_regs();
pmsyncreg = read32(pmcbase + PMSYNC_TPR_CFG);
pmsyncreg |= PCH2CPU_TPR_CFG_LOCK;
write32(pmcbase + PMSYNC_TPR_CFG, pmsyncreg);
}
static void pmc_lock_abase(void)
{
uint8_t *pmcbase;
uint32_t reg32;
pmcbase = pmc_mmio_regs();
reg32 = read32(pmcbase + GEN_PMCON_B);
reg32 |= (SLP_STR_POL_LOCK | ACPI_BASE_LOCK);
write32(pmcbase + GEN_PMCON_B, reg32);
}
static void pmc_lock_smi(void)
{
uint8_t *pmcbase;
uint8_t reg8;
pmcbase = pmc_mmio_regs();
reg8 = read8(pmcbase + GEN_PMCON_B);
reg8 |= SMI_LOCK;
write8(pmcbase + GEN_PMCON_B, reg8);
}
static void pmc_lockdown_cfg(int chipset_lockdown)
{
/* PMSYNC */
pmc_lock_pmsync();
/* Lock down ABASE and sleep stretching policy */
pmc_lock_abase();
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT)
pmc_lock_smi();
}
void soc_lockdown_config(int chipset_lockdown)
{
/* PMC lock down configuration */
pmc_lockdown_cfg(chipset_lockdown);
}

View File

@@ -0,0 +1,167 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <intelblocks/cse.h>
#include <console/console.h>
#include <soc/me.h>
#include <stdint.h>
/* Host Firmware Status Register 2 */
union me_hfsts2 {
uint32_t data;
struct {
uint32_t nftp_load_failure : 1;
uint32_t icc_prog_status : 2;
uint32_t invoke_mebx : 1;
uint32_t cpu_replaced : 1;
uint32_t rsvd0 : 1;
uint32_t mfs_failure : 1;
uint32_t warm_reset_rqst : 1;
uint32_t cpu_replaced_valid : 1;
uint32_t low_power_state : 1;
uint32_t me_power_gate : 1;
uint32_t ipu_needed : 1;
uint32_t forced_safe_boot : 1;
uint32_t rsvd1 : 2;
uint32_t listener_change : 1;
uint32_t status_data : 8;
uint32_t current_pmevent : 4;
uint32_t phase : 4;
} __packed fields;
};
/* Host Firmware Status Register 4 */
union me_hfsts4 {
uint32_t data;
struct {
uint32_t rsvd0 : 9;
uint32_t enforcement_flow : 1;
uint32_t sx_resume_type : 1;
uint32_t rsvd1 : 1;
uint32_t tpms_disconnected : 1;
uint32_t rvsd2 : 1;
uint32_t fwsts_valid : 1;
uint32_t boot_guard_self_test : 1;
uint32_t rsvd3 : 16;
} __packed fields;
};
/* Host Firmware Status Register 5 */
union me_hfsts5 {
uint32_t data;
struct {
uint32_t acm_active : 1;
uint32_t valid : 1;
uint32_t result_code_source : 1;
uint32_t error_status_code : 5;
uint32_t acm_done_sts : 1;
uint32_t timeout_count : 7;
uint32_t scrtm_indicator : 1;
uint32_t inc_boot_guard_acm : 4;
uint32_t inc_key_manifest : 4;
uint32_t inc_boot_policy : 4;
uint32_t rsvd0 : 2;
uint32_t start_enforcement : 1;
} __packed fields;
};
/* Host Firmware Status Register 6 */
union me_hfsts6 {
uint32_t data;
struct {
uint32_t force_boot_guard_acm : 1;
uint32_t cpu_debug_disable : 1;
uint32_t bsp_init_disable : 1;
uint32_t protect_bios_env : 1;
uint32_t rsvd0 : 2;
uint32_t error_enforce_policy : 2;
uint32_t measured_boot : 1;
uint32_t verified_boot : 1;
uint32_t boot_guard_acmsvn : 4;
uint32_t kmsvn : 4;
uint32_t bpmsvn : 4;
uint32_t key_manifest_id : 4;
uint32_t boot_policy_status : 1;
uint32_t error : 1;
uint32_t boot_guard_disable : 1;
uint32_t fpf_disable : 1;
uint32_t fpf_soc_lock : 1;
uint32_t txt_support : 1;
} __packed fields;
};
static void dump_me_status(void *unused)
{
union me_hfsts1 hfsts1;
union me_hfsts2 hfsts2;
union me_hfsts3 hfsts3;
union me_hfsts4 hfsts4;
union me_hfsts5 hfsts5;
union me_hfsts6 hfsts6;
if (!is_cse_enabled())
return;
hfsts1.data = me_read_config32(PCI_ME_HFSTS1);
hfsts2.data = me_read_config32(PCI_ME_HFSTS2);
hfsts3.data = me_read_config32(PCI_ME_HFSTS3);
hfsts4.data = me_read_config32(PCI_ME_HFSTS4);
hfsts5.data = me_read_config32(PCI_ME_HFSTS5);
hfsts6.data = me_read_config32(PCI_ME_HFSTS6);
printk(BIOS_DEBUG, "ME: HFSTS1 : 0x%08X\n", hfsts1.data);
printk(BIOS_DEBUG, "ME: HFSTS2 : 0x%08X\n", hfsts2.data);
printk(BIOS_DEBUG, "ME: HFSTS3 : 0x%08X\n", hfsts3.data);
printk(BIOS_DEBUG, "ME: HFSTS4 : 0x%08X\n", hfsts4.data);
printk(BIOS_DEBUG, "ME: HFSTS5 : 0x%08X\n", hfsts5.data);
printk(BIOS_DEBUG, "ME: HFSTS6 : 0x%08X\n", hfsts6.data);
/*
* Lock Descriptor, and Fuses must be programmed on a
* production system to indicate ME Manufacturing mode is disabled.
*/
printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
((hfsts1.fields.mfg_mode == 0) &&
(hfsts6.fields.fpf_soc_lock == 1)) ? "NO" : "YES");
/*
* The SPI Protection Mode bit reflects SPI descriptor
* locked(0) or unlocked(1).
*/
printk(BIOS_DEBUG, "ME: SPI Protection Mode Enabled : %s\n",
hfsts1.fields.mfg_mode ? "NO" : "YES");
printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n",
hfsts1.fields.fpt_bad ? "BAD" : "OK");
printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n",
hfsts1.fields.ft_bup_ld_flr ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n",
hfsts1.fields.fw_init_complete ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n",
hfsts1.fields.boot_options_present ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Update In Progress : %s\n",
hfsts1.fields.update_in_progress ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: D0i3 Support : %s\n",
hfsts1.fields.d0i3_support_valid ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
hfsts2.fields.low_power_state ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: CPU Replaced : %s\n",
hfsts2.fields.cpu_replaced ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: CPU Replacement Valid : %s\n",
hfsts2.fields.cpu_replaced_valid ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Current Working State : %u\n",
hfsts1.fields.working_state);
printk(BIOS_DEBUG, "ME: Current Operation State : %u\n",
hfsts1.fields.operation_state);
printk(BIOS_DEBUG, "ME: Current Operation Mode : %u\n",
hfsts1.fields.operation_mode);
printk(BIOS_DEBUG, "ME: Error Code : %u\n",
hfsts1.fields.error_code);
printk(BIOS_DEBUG, "ME: Enhanced Debug Mode : %s\n",
hfsts1.fields.invoke_enhance_dbg_mode ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: CPU Debug Disabled : %s\n",
hfsts6.fields.cpu_debug_disable ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: TXT Support : %s\n",
hfsts6.fields.txt_support ? "YES" : "NO");
}
BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_EXIT, print_me_fw_version, NULL);
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK, BS_ON_EXIT, dump_me_status, NULL);

View File

@@ -1,7 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h> #include <console/console.h>
#include <device/device.h>
#include <intelblocks/p2sb.h> #include <intelblocks/p2sb.h>
#include <soc/iomap.h>
void p2sb_soc_get_sb_mask(uint32_t *ep_mask, size_t count) void p2sb_soc_get_sb_mask(uint32_t *ep_mask, size_t count)
{ {
@@ -28,3 +30,15 @@ void p2sb_soc_get_sb_mask(uint32_t *ep_mask, size_t count)
ep_mask[P2SB_EP_MASK_7_REG] = mask; ep_mask[P2SB_EP_MASK_7_REG] = mask;
} }
static void ioe_p2sb_read_resources(struct device *dev)
{
/* Add the fixed MMIO resource for IOM */
mmio_resource_kb(dev, 0, IOM_BASE_ADDR / KiB, IOM_BASE_SIZE / KiB);
}
struct device_operations ioe_p2sb_ops = {
.read_resources = ioe_p2sb_read_resources,
.set_resources = noop_set_resources,
.scan_bus = scan_static_bus,
};

View File

@@ -0,0 +1,29 @@
/* 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>
#include <console/console.h>
static const struct pcie_rp_group mtlp_rp_groups[] = {
{ .slot = PCI_DEV_SLOT_PCIE_1, .start = 0, .count = 8, .lcap_port_base = 1 },
{ .slot = PCI_DEV_SLOT_PCIE_2, .start = 0, .count = 3, .lcap_port_base = 1 },
{ .slot = PCI_DEV_SLOT_PCIE_3, .start = 0, .count = 1, .lcap_port_base = 1 },
{ 0 }
};
const struct pcie_rp_group *get_pcie_rp_table(void)
{
return mtlp_rp_groups;
}
enum pcie_rp_type soc_get_pcie_rp_type(const struct device *dev)
{
return PCIE_RP_PCH;
}
int soc_get_cpu_rp_vw_idx(const struct device *dev)
{
return -1;
}

View File

@@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/mmio.h>
#include <device/device.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>
#include <bootstate.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();
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_resource_kb(dev, 0, PCH_PWRM_BASE_ADDRESS / KiB, PCH_PWRM_BASE_SIZE / KiB);
/* 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) Meteor Lake IPC Controller");
/*
* 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 mtl_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(&mtl_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
* TGL has its PMC device available for device_operations, it can be
* done from the "ops->init" callback.
*/
pmc_set_acpi_mode();
/*
* Disable ACPI PM timer based on Kconfig
*
* Disabling ACPI PM timer is necessary for XTAL OSC shutdown.
* Disabling ACPI PM timer also switches off TCO
*/
if (!CONFIG(USE_PM_ACPI_TIMER))
setbits8(pmc_mmio_regs() + PCH_PWRM_ACPI_TMR_CTL, ACPI_TIM_DIS);
}
static void pm1_enable_pwrbtn_smi(void *unused)
{
/* Enable power button SMI after BS_DEV_INIT_CHIPS (FSP-S) is done. */
pmc_update_pm1_enable(PWRBTN_EN);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, pm1_enable_pwrbtn_smi, NULL);
/*
* `pmc_final` function is native implementation of equivalent events performed by
* each FSP NotifyPhase() API invocations.
*
*
* Clear PMCON status bits (Global Reset/Power Failure/Host Reset Status bits)
*
* Perform the PMCON status bit clear operation from `.final`
* to cover any such chances where later boot stage requested a global
* reset and PMCON status bit remains set.
*/
static void pmc_final(struct device *dev)
{
pmc_clear_pmcon_sts();
}
struct device_operations pmc_ops = {
.read_resources = soc_pmc_read_resources,
.set_resources = noop_set_resources,
.init = soc_pmc_init,
.enable = soc_pmc_enable,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_fill_ssdt = soc_pmc_fill_ssdt,
#endif
.scan_bus = scan_static_bus,
.final = pmc_final,
};

View File

@@ -0,0 +1,265 @@
/* 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 <device/mmio.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_def.h>
#include <console/console.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/rtc.h>
#include <intelblocks/tco.h>
#include <security/vboot/vbnv.h>
#include <soc/espi.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_meteorlake_config *config;
config = config_of_soc();
/* 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_pm_state_for_rtc(&ps) < 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->gen_pmcon_a & (PWR_FLR | SUS_PWR_FLR))
prev_sleep_state = ACPI_S5;
/*
* If waking from S3 determine if deep S3 is enabled. If not,
* need to check both deep sleep well and normal suspend well.
* Otherwise just check deep sleep well.
*/
if (prev_sleep_state == ACPI_S3) {
/* PWR_FLR represents deep sleep power well loss. */
uint32_t mask = PWR_FLR;
/* If deep s3 isn't enabled check the suspend well too. */
if (!deep_s3_enabled())
mask |= SUS_PWR_FLR;
if (ps->gen_pmcon_a & mask)
prev_sleep_state = ACPI_S5;
}
return prev_sleep_state;
}
void soc_fill_power_state(struct chipset_power_state *ps)
{
uint8_t *pmc;
ps->tco1_sts = tco_read_reg(TCO1_STS);
ps->tco2_sts = tco_read_reg(TCO2_STS);
printk(BIOS_DEBUG, "TCO_STS: %04x %04x\n", ps->tco1_sts, ps->tco2_sts);
pmc = pmc_mmio_regs();
ps->gen_pmcon_a = read32(pmc + GEN_PMCON_A);
ps->gen_pmcon_b = read32(pmc + GEN_PMCON_B);
ps->gblrst_cause[0] = read32(pmc + GBLRST_CAUSE0);
ps->gblrst_cause[1] = read32(pmc + GBLRST_CAUSE1);
ps->hpr_cause0 = read32(pmc + HPR_CAUSE0);
printk(BIOS_DEBUG, "GEN_PMCON: %08x %08x\n",
ps->gen_pmcon_a, ps->gen_pmcon_b);
printk(BIOS_DEBUG, "GBLRST_CAUSE: %08x %08x\n",
ps->gblrst_cause[0], ps->gblrst_cause[1]);
printk(BIOS_DEBUG, "HPR_CAUSE0: %08x\n", ps->hpr_cause0);
}
/* STM Support */
uint16_t get_pmbase(void)
{
return (uint16_t) ACPI_BASE_ADDRESS;
}
/*
* Set which power state system will be after reapplying
* the power (from G3 State)
*/
void pmc_soc_set_afterg3_en(const bool on)
{
uint8_t reg8;
uint8_t *const pmcbase = pmc_mmio_regs();
reg8 = read8(pmcbase + GEN_PMCON_A);
if (on)
reg8 &= ~SLEEP_AFTER_POWER_FAIL;
else
reg8 |= SLEEP_AFTER_POWER_FAIL;
write8(pmcbase + GEN_PMCON_A, reg8);
}

View File

@@ -0,0 +1,32 @@
/* 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)
{
int ec_port = 0;
const struct device *tcss_port_arr[] = {
DEV_PTR(tcss_usb3_port1),
DEV_PTR(tcss_usb3_port2),
DEV_PTR(tcss_usb3_port3),
DEV_PTR(tcss_usb3_port4),
};
for (uint8_t i = 0; i < MAX_TYPE_C_PORTS; i++) {
if (i == typec_port) {
printk(BIOS_ERR, "USB Type-C %d mapped to EC port %d\n", typec_port,
ec_port);
return ec_port;
}
if (is_dev_enabled(tcss_port_arr[i]))
ec_port++;
}
// Code should not come here if typec_port input is correct
return -1;
}

View File

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

View File

@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <soc/pci_devs.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <soc/soc_info.h>
#include <intelblocks/tcss.h>
#include <console/console.h>
uint8_t get_max_usb20_port(void)
{
uint8_t usb20_port = CONFIG_SOC_INTEL_USB2_DEV_MAX;
printk(BIOS_DEBUG, "soc_info: max_usb20_port:%d\n", usb20_port);
return usb20_port;
}
uint8_t get_max_usb30_port(void)
{
uint8_t usb30_port = CONFIG_SOC_INTEL_USB3_DEV_MAX;
printk(BIOS_DEBUG, "soc_info: max_usb30_port:%d\n", usb30_port);
return usb30_port;
}
uint8_t get_max_tcss_port(void)
{
uint8_t tcss_port = MAX_TYPE_C_PORTS;
printk(BIOS_DEBUG, "soc_info: tcss_port:%d\n", tcss_port);
return tcss_port;
}
uint8_t get_max_tbt_pcie_port(void)
{
uint8_t tbt_pcie_port = CONFIG_MAX_TBT_ROOT_PORTS;
printk(BIOS_DEBUG, "soc_info: max_tbt_pcie_port:%d\n", tbt_pcie_port);
return tbt_pcie_port;
}
uint8_t get_max_pcie_port(void)
{
uint8_t pcie_port = CONFIG_MAX_ROOT_PORTS;
printk(BIOS_DEBUG, "soc_info: max_pcie_port:%d\n", pcie_port);
return pcie_port;
}
uint8_t get_max_pcie_clock(void)
{
uint8_t pcie_clock = CONFIG_MAX_PCIE_CLOCK_SRC;
printk(BIOS_DEBUG, "soc_info: max_pcie_clock:%d\n", pcie_clock);
return pcie_clock;
}
uint8_t get_max_uart_port(void)
{
uint8_t uart_port = CONFIG_SOC_INTEL_UART_DEV_MAX;
printk(BIOS_DEBUG, "soc_info: max_uart_port:%d\n", uart_port);
return uart_port;
}
uint8_t get_max_i2c_port(void)
{
uint8_t i2c_port = CONFIG_SOC_INTEL_I2C_DEV_MAX;
printk(BIOS_DEBUG, "soc_info: max_i2c_port:%d\n", i2c_port);
return i2c_port;
}
uint8_t get_max_gspi_port(void)
{
uint8_t gspi_port = CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX;
printk(BIOS_DEBUG, "soc_info: max_gspi_port:%d\n", gspi_port);
return gspi_port;
}

View File

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

View File

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

View File

@@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <delay.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[] = {
{ PCIEXBAR, CONFIG_ECAM_MMCONF_BASE_ADDRESS, CONFIG_ECAM_MMCONF_LENGTH,
"PCIEXBAR" },
{ DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" },
{ EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
{ REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
{ EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" },
};
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));
}
/*
* SoC implementation
*
* Perform System Agent Initialization during Ramstage phase.
*/
void soc_systemagent_init(struct device *dev)
{
struct soc_power_limits_config *soc_config;
struct device *sa;
uint16_t sa_pci_id;
config_t *config;
/* Enable Power Aware Interrupt Routing */
enable_power_aware_intr();
/* Enable BIOS Reset CPL */
enable_bios_reset_cpl();
/* Configure turbo power limits 1ms after reset complete bit */
mdelay(1);
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;
/* Choose a power limits configuration based on the SoC SKU type,
* differentiated here based on SA PCI ID. */
switch (sa_pci_id) {
case PCI_DID_INTEL_MTL_P_ID_1:
soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_1];
break;
case PCI_DID_INTEL_MTL_P_ID_2:
soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_2];
break;
case PCI_DID_INTEL_MTL_P_ID_3:
soc_config = &config->power_limits_config[MTL_P_POWER_LIMITS_3];
break;
default:
printk(BIOS_ERR, "unknown SA ID: 0x%4x, skipping power limits configuration\n",
sa_pci_id);
return;
}
/* UPDATEME: Need to enable later */
//set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
}
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
{
switch (capid0_a_ddrsz) {
case 1:
return 8192;
case 2:
return 4096;
case 3:
return 2048;
default:
return 65536;
}
}

View File

@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <intelblocks/tcss.h>
const struct soc_tcss_ops tcss_ops = {
.configure_aux_bias_pads = tcss_configure_aux_bias_pads_regbar,
.valid_tbt_auth = tcss_valid_tbt_auth,
};

View File

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

View File

@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pci_type.h>
#include <intelblocks/xhci.h>
#include <soc/pci_devs.h>
#define XHCI_USB2_PORT_STATUS_REG 0x480
#define XHCI_USB3_PORT_STATUS_REG 0x540
#define XHCI_USB2_PORT_NUM 10
#define XHCI_USB3_PORT_NUM 4
#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;
}