diff options
42 files changed, 4617 insertions, 3 deletions
diff --git a/src/soc/intel/elkhartlake/Kconfig b/src/soc/intel/elkhartlake/Kconfig new file mode 100644 index 0000000000..166bda01cc --- /dev/null +++ b/src/soc/intel/elkhartlake/Kconfig @@ -0,0 +1,213 @@ +config SOC_INTEL_ELKHARTLAKE + bool + help + Intel Elkhartlake support + +if SOC_INTEL_ELKHARTLAKE + +config CPU_SPECIFIC_OPTIONS + def_bool y + select ACPI_INTEL_HARDWARE_SLEEP_VALUES + select ARCH_BOOTBLOCK_X86_32 + select ARCH_RAMSTAGE_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_VERSTAGE_X86_32 + select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH + select BOOT_DEVICE_SUPPORTS_WRITES + select CACHE_MRC_SETTINGS + select CPU_INTEL_COMMON + select CPU_INTEL_FIRMWARE_INTERFACE_TABLE + select FSP_COMPRESS_FSP_S_LZ4 + select FSP_M_XIP + select GENERIC_GPIO_LIB + select HAVE_FSP_GOP + select INTEL_DESCRIPTOR_MODE_CAPABLE + select HAVE_SMI_HANDLER + select IDT_IN_EVERY_STAGE + select INTEL_CAR_NEM #TODO - Enable INTEL_CAR_NEM_ENHANCED + select INTEL_GMA_ACPI + select INTEL_GMA_ADD_VBT if RUN_FSP_GOP + select IOAPIC + select MRC_SETTINGS_PROTECT + select PARALLEL_MP + select PARALLEL_MP_AP_WORK + select MICROCODE_BLOB_UNDISCLOSED + select PLATFORM_USES_FSP2_2 + select FSP_PEIM_TO_PEIM_INTERFACE + select REG_SCRIPT + select PMC_GLOBAL_RESET_ENABLE_LOCK + select CPU_INTEL_COMMON_SMM + select SOC_INTEL_COMMON + select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE + select SOC_INTEL_COMMON_BLOCK + select SOC_INTEL_COMMON_BLOCK_ACPI + select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG + select SOC_INTEL_COMMON_BLOCK_CPU + select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT + select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT + select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2 + select SOC_INTEL_COMMON_BLOCK_HDA + select SOC_INTEL_COMMON_BLOCK_SA + select SOC_INTEL_COMMON_BLOCK_SCS + select SOC_INTEL_COMMON_BLOCK_SMM + select SOC_INTEL_COMMON_BLOCK_POWER_LIMIT + select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP + select SOC_INTEL_COMMON_PCH_BASE + select SOC_INTEL_COMMON_RESET + select SOC_INTEL_COMMON_BLOCK_CAR + select SSE2 + select SUPPORT_CPU_UCODE_IN_CBFS + select TSC_MONOTONIC_TIMER + select UDELAY_TSC + select UDK_202005_BINDING + select DISPLAY_FSP_VERSION_INFO + select HECI_DISABLE_USING_SMM + +config DCACHE_RAM_BASE + default 0xfef00000 + +config DCACHE_RAM_SIZE + default 0x80000 + help + The size of the cache-as-ram region required during bootblock + and/or romstage. + +config DCACHE_BSP_STACK_SIZE + hex + default 0x30400 + help + The amount of anticipated stack usage in CAR by bootblock and + other stages. In the case of FSP_USES_CB_STACK default value + will be sum of FSP-M stack requirement(192 KiB) and CB romstage + stack requirement(~1KiB). + +config FSP_TEMP_RAM_SIZE + hex + default 0x20000 + help + The amount of anticipated heap usage in CAR by FSP. + Refer to Platform FSP integration guide document to know + the exact FSP requirement for Heap setup. + +config IFD_CHIPSET + string + default "ehl" + +config IED_REGION_SIZE + hex + default 0x400000 + +config HEAP_SIZE + hex + default 0x8000 + +config MAX_ROOT_PORTS + int + default 8 + +config MAX_PCIE_CLOCKS + int + default 6 + +config SMM_TSEG_SIZE + hex + default 0x800000 + +config SMM_RESERVED_SIZE + hex + default 0x200000 + +config PCR_BASE_ADDRESS + hex + default 0xfd000000 + help + This option allows you to select MMIO Base Address of sideband bus. + +config MMCONF_BASE_ADDRESS + hex + default 0xc0000000 + +config CPU_BCLK_MHZ + int + default 100 + +config SOC_INTEL_COMMON_BLOCK_GSPI_CLOCK_MHZ + int + default 120 + +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default 133 + +config SOC_INTEL_COMMON_BLOCK_GSPI_MAX + int + default 3 + +config SOC_INTEL_I2C_DEV_MAX + int + default 6 + +config SOC_INTEL_UART_DEV_MAX + int + default 3 + +config CONSOLE_UART_BASE_ADDRESS + hex + default 0xfe032000 + depends on INTEL_LPSS_UART_FOR_CONSOLE + +# Clock divider parameters for 115200 baud rate +# Baudrate = (UART source clcok * M) /(N *16) +# EHL UART source clock: 100MHz +config SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL + hex + default 0x30 + +config SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL + hex + default 0xc35 + +config CHROMEOS + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT + select VBOOT_SEPARATE_VERSTAGE + select VBOOT_MUST_REQUEST_DISPLAY + select VBOOT_STARTS_IN_BOOTBLOCK + select VBOOT_VBNV_CMOS + select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH + +config C_ENV_BOOTBLOCK_SIZE + hex + default 0xC000 + +config CBFS_SIZE + hex + default 0x200000 + +config FSP_HEADER_PATH + default "src/vendorcode/intel/fsp/fsp2_0/elkhartlake/" + +config FSP_FD_PATH + default "3rdparty/fsp/ElkhartLakeFspBinPkg/Fsp.fd" + +config SOC_INTEL_ELKHARTLAKE_DEBUG_CONSENT + int "Debug Consent for EHL" + # USB DBC is more common for developers so make this default to 3 if + # SOC_INTEL_DEBUG_CONSENT=y + default 3 if SOC_INTEL_DEBUG_CONSENT + default 0 + help + This is to control debug interface on SOC. + Setting non-zero value will allow to use DBC or DCI to debug SOC. + PlatformDebugConsent in FspmUpd.h has the details. + + Desired platform debug type are + 0:Disabled, 1:Enabled (DCI OOB+[DbC]), 2:Enabled (DCI OOB), + 3:Enabled (USB3 DbC), 4:Enabled (XDP/MIPI60), 5:Enabled (USB2 DbC), + 6:Enable (2-wire DCI OOB), 7:Manual + +config PRERAM_CBMEM_CONSOLE_SIZE + hex + default 0x1400 +endif diff --git a/src/soc/intel/elkhartlake/Makefile.inc b/src/soc/intel/elkhartlake/Makefile.inc new file mode 100644 index 0000000000..5c46f86738 --- /dev/null +++ b/src/soc/intel/elkhartlake/Makefile.inc @@ -0,0 +1,60 @@ +ifeq ($(CONFIG_SOC_INTEL_ELKHARTLAKE),y) + +subdirs-y += romstage +subdirs-y += ../../../cpu/intel/microcode +subdirs-y += ../../../cpu/intel/turbo +subdirs-y += ../../../cpu/x86/lapic +subdirs-y += ../../../cpu/x86/mtrr +subdirs-y += ../../../cpu/x86/smm +subdirs-y += ../../../cpu/x86/tsc + +# 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/cpu.c +bootblock-y += bootblock/pch.c +bootblock-y += bootblock/report_platform.c +bootblock-y += espi.c +bootblock-y += gpio.c +bootblock-y += p2sb.c + +romstage-y += espi.c +romstage-y += gpio.c +romstage-y += meminit.c +romstage-y += reset.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 += gpio.c +ramstage-y += lockdown.c +ramstage-y += p2sb.c +ramstage-y += pmc.c +ramstage-y += reset.c +ramstage-y += smmrelocate.c +ramstage-y += systemagent.c +ramstage-y += sd.c +ramstage-y += me.c + +smm-y += gpio.c +smm-y += p2sb.c +smm-y += pmc.c +smm-y += pmutil.c +smm-y += smihandler.c +smm-y += uart.c + +verstage-y += gpio.c + +CPPFLAGS_common += -I$(src)/soc/intel/elkhartlake +CPPFLAGS_common += -I$(src)/soc/intel/elkhartlake/include + +endif diff --git a/src/soc/intel/elkhartlake/acpi.c b/src/soc/intel/elkhartlake/acpi.c new file mode 100644 index 0000000000..af837aba5d --- /dev/null +++ b/src/soc/intel/elkhartlake/acpi.c @@ -0,0 +1,343 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <acpi/acpi.h> +#include <acpi/acpi_gnvs.h> +#include <acpi/acpigen.h> +#include <arch/smp/mpspec.h> +#include <cbmem.h> +#include <console/console.h> +#include <device/device.h> +#include <device/mmio.h> +#include <device/pci_ops.h> +#include <ec/google/chromeec/ec.h> +#include <intelblocks/acpi.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/pmclib.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 <wrdd.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 +}; + +#define MWAIT_RES(state, sub_state) \ + { \ + .addrl = (((state) << 4) | (sub_state)), \ + .space_id = ACPI_ADDRESS_SPACE_FIXED, \ + .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \ + .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \ + .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \ + } + +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 +}; + +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++) { + memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t)); + 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_UNDEFINED; + 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) +{ + uintptr_t pmc_bar = soc_read_pmc_base(); + return read32((void *)pmc_bar + IRQ_REG); +} + +static unsigned long soc_fill_dmar(unsigned long current) +{ + const struct device *const igfx_dev = pcidev_path_on_root(SA_DEVFN_IGD); + uint64_t gfxvtbar = MCHBAR64(GFXVTBAR) & VTBAR_MASK; + bool gfxvten = MCHBAR32(GFXVTBAR) & VTBAR_ENABLED; + + if (is_dev_enabled(igfx_dev) && gfxvtbar && gfxvten) { + unsigned long tmp = current; + + current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar); + current += acpi_create_dmar_ds_pci(current, 0, 2, 0); + + acpi_dmar_drhd_fixup(tmp, current); + } + + uint64_t vtvc0bar = MCHBAR64(VTVC0BAR) & VTBAR_MASK; + bool vtvc0en = MCHBAR32(VTVC0BAR) & VTBAR_ENABLED; + + if (vtvc0bar && vtvc0en) { + const unsigned long tmp = current; + + current += acpi_create_dmar_drhd(current, + DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar); + 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 */ + 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, 2, 0); + acpi_dmar_rmrr_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(VTVC0BAR) & 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 acpi_create_gnvs(struct global_nvs *gnvs) +{ + config_t *config = config_of_soc(); + + /* Set unknown wake source */ + gnvs->pm1i = -1; + + /* CPU core count */ + gnvs->pcnt = dev_count_cpu(); + + if (CONFIG(CONSOLE_CBMEM)) + /* Update the mem console pointer. */ + gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE); + + if (CONFIG(CHROMEOS)) { + /* Initialize Verified Boot data */ + chromeos_init_chromeos_acpi(&(gnvs->chromeos)); + if (CONFIG(EC_GOOGLE_CHROMEEC)) { + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; + } else + gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; + } + + /* Enable DPTF based on mainboard configuration */ + gnvs->dpte = config->dptf_enable; + + /* Fill in the Wifi Region id */ + gnvs->cid1 = wifi_regulatory_domain(); + + /* Set USB2/USB3 wake enable bitmaps. */ + gnvs->u2we = config->usb2_wake_enable_bitmap; + gnvs->u3we = config->usb3_wake_enable_bitmap; + + /* Fill in Above 4GB MMIO resource */ + sa_fill_gnvs(gnvs); +} + +uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en, + const struct chipset_power_state *ps) +{ + /* + * WAK_STS bit is set when the system is in one of the sleep states + * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting + * this bit, the PMC will transition the system to the ON state and + * can only be set by hardware and can only be cleared by writing a one + * to this bit position. + */ + + generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN; + return generic_pm1_en; +} + +int soc_madt_sci_irq_polarity(int sci) +{ + return MP_IRQ_POLARITY_HIGH; +} + +static int acpigen_soc_gpio_op(const char *op, unsigned int gpio_num) +{ + /* op (gpio_num) */ + acpigen_emit_namestring(op); + acpigen_write_integer(gpio_num); + return 0; +} + +static int acpigen_soc_get_gpio_state(const char *op, unsigned int gpio_num) +{ + /* Store (op (gpio_num), Local0) */ + acpigen_write_store(); + acpigen_soc_gpio_op(op, gpio_num); + acpigen_emit_byte(LOCAL0_OP); + return 0; +} + +int acpigen_soc_read_rx_gpio(unsigned int gpio_num) +{ + return acpigen_soc_get_gpio_state("\\_SB.PCI0.GRXS", gpio_num); +} + +int acpigen_soc_get_tx_gpio(unsigned int gpio_num) +{ + return acpigen_soc_get_gpio_state("\\_SB.PCI0.GTXS", gpio_num); +} + +int acpigen_soc_set_tx_gpio(unsigned int gpio_num) +{ + return acpigen_soc_gpio_op("\\_SB.PCI0.STXS", gpio_num); +} + +int acpigen_soc_clear_tx_gpio(unsigned int gpio_num) +{ + return acpigen_soc_gpio_op("\\_SB.PCI0.CTXS", gpio_num); +} diff --git a/src/soc/intel/elkhartlake/chip.c b/src/soc/intel/elkhartlake/chip.c new file mode 100644 index 0000000000..e4884efea1 --- /dev/null +++ b/src/soc/intel/elkhartlake/chip.c @@ -0,0 +1,180 @@ +/* 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/itss.h> +#include <intelblocks/pcie_rp.h> +#include <intelblocks/xdci.h> +#include <romstage_handoff.h> +#include <soc/intel/common/vbt.h> +#include <soc/itss.h> +#include <soc/pci_devs.h> +#include <soc/ramstage.h> +#include <soc/soc_chip.h> + +static const struct pcie_rp_group pch_rp_groups[] = { + { .slot = PCH_DEV_SLOT_PCIE, .count = 8 }, + { 0 } +}; + +#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; + } + return NULL; + } + if (dev->path.type != DEVICE_PATH_PCI) + return NULL; + + switch (dev->path.pci.devfn) { + case SA_DEVFN_ROOT: return "MCHC"; + case SA_DEVFN_IPU: return "IPU0"; + case PCH_DEVFN_ISH: return "ISHB"; + case PCH_DEVFN_XHCI: return "XHCI"; + case PCH_DEVFN_I2C0: return "I2C0"; + case PCH_DEVFN_I2C1: return "I2C1"; + case PCH_DEVFN_I2C2: return "I2C2"; + case PCH_DEVFN_I2C3: return "I2C3"; + case PCH_DEVFN_I2C4: return "I2C4"; + case PCH_DEVFN_I2C5: return "I2C5"; + case PCH_DEVFN_SATA: return "SATA"; + case PCH_DEVFN_PCIE1: return "RP01"; + case PCH_DEVFN_PCIE2: return "RP02"; + case PCH_DEVFN_PCIE3: return "RP03"; + case PCH_DEVFN_PCIE4: return "RP04"; + case PCH_DEVFN_PCIE5: return "RP05"; + case PCH_DEVFN_PCIE6: return "RP06"; + case PCH_DEVFN_PCIE7: return "RP07"; + case PCH_DEVFN_PCIE8: return "RP08"; + case PCH_DEVFN_PCIE9: return "RP09"; + case PCH_DEVFN_PCIE10: return "RP10"; + case PCH_DEVFN_PCIE11: return "RP11"; + case PCH_DEVFN_PCIE12: return "RP12"; + case PCH_DEVFN_UART0: return "UAR0"; + case PCH_DEVFN_UART1: return "UAR1"; + case PCH_DEVFN_UART2: return "UAR2"; + case PCH_DEVFN_GSPI0: return "SPI0"; + case PCH_DEVFN_GSPI1: return "SPI1"; + case PCH_DEVFN_GSPI2: return "SPI2"; + case PCH_DEVFN_GSPI3: return "SPI3"; + case PCH_DEVFN_EMMC: return "EMMC"; + case PCH_DEVFN_SDCARD: return "SDXC"; + /* Keeping ACPI device name coherent with ec.asl */ + case PCH_DEVFN_ESPI: return "LPCB"; + case PCH_DEVFN_HDA: return "HDAS"; + case PCH_DEVFN_SMBUS: return "SBUS"; + case PCH_DEVFN_GBE: return "GLAN"; + } + + return NULL; +} +#endif + +/* SoC rotine 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(uint8_t) * + TOTAL_GPIO_COMM); + else + memset(value, MISCCFG_ENABLE_GPIO_PM_CONFIG, sizeof(uint8_t) * + TOTAL_GPIO_COMM); + + gpio_pm_configure(value, TOTAL_GPIO_COMM); +} + +void soc_init_pre_device(void *chip_info) +{ + /* Snapshot the current GPIO IRQ polarities. FSP is setting a + * default policy that doesn't honor boards' requirements. */ + itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END); + + /* Perform silicon specific init. */ + fsp_silicon_init(romstage_handoff_is_resume()); + + /* Display FIRMWARE_VERSION_INFO_HOB */ + fsp_display_fvi_version_hob(); + + /* Restore GPIO IRQ polarities back to previous settings. */ + itss_restore_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END); + + soc_fill_gpio_pm_configuration(); + + /* swap enabled PCI ports in device tree if needed */ + pcie_rp_update_devicetree(pch_rp_groups); +} + +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, +#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 +}; + +extern struct device_operations pmc_ops; +static void soc_enable(struct device *dev) +{ + /* Set the operations if it is a special bus type */ + 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 == PCH_DEVFN_PMC) + dev->ops = &pmc_ops; +} + +struct chip_operations soc_intel_elkhartlake_ops = { + CHIP_NAME("Intel Elkhartlake") + .enable_dev = &soc_enable, + .init = &soc_init_pre_device, +}; diff --git a/src/soc/intel/elkhartlake/chip.h b/src/soc/intel/elkhartlake/chip.h new file mode 100644 index 0000000000..5037147d74 --- /dev/null +++ b/src/soc/intel/elkhartlake/chip.h @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_CHIP_H_ +#define _SOC_CHIP_H_ + +#include <drivers/i2c/designware/dw_i2c.h> +#include <intelblocks/cfg.h> +#include <intelblocks/gpio.h> +#include <intelblocks/gspi.h> +#include <intelblocks/power_limit.h> +#include <soc/gpe.h> +#include <soc/gpio.h> +#include <soc/gpio_defs.h> +#include <soc/pch.h> +#include <soc/pci_devs.h> +#include <soc/pmc.h> +#include <soc/serialio.h> +#include <soc/usb.h> +#include <stdint.h> + +#define MAX_HD_AUDIO_DMIC_LINKS 2 +#define MAX_HD_AUDIO_SNDW_LINKS 4 +#define MAX_HD_AUDIO_SSP_LINKS 6 + +struct soc_intel_elkhartlake_config { + + /* Common struct containing soc config data required by common code */ + struct soc_intel_common_config common_soc_config; + + /* Common struct containing power limits configuration information */ + struct soc_power_limits_config power_limits_config; + + /* Gpio group routed to each dword of the GPE0 block. Values are + * 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 */ + + /* Generic IO decode ranges */ + uint32_t gen1_dec; + uint32_t gen2_dec; + uint32_t gen3_dec; + uint32_t gen4_dec; + + /* Enable S0iX support */ + int s0ix_enable; + /* Enable DPTF support */ + int 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; + + /* 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 */ + uint32_t deep_sx_config; + + /* TCC activation offset */ + uint32_t tcc_offset; + + /* 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 */ + enum { + SaGv_Disabled, + SaGv_FixedPoint0, + SaGv_FixedPoint1, + SaGv_FixedPoint2, + SaGv_FixedPoint3, + SaGv_Enabled, + } SaGv; + + /* Rank Margin Tool. 1:Enable, 0:Disable */ + uint8_t RMT; + + /* USB related */ + struct usb2_port_config usb2_ports[16]; + struct usb3_port_config usb3_ports[10]; + /* Wake Enable Bitmap for USB2 ports */ + uint16_t usb2_wake_enable_bitmap; + /* Wake Enable Bitmap for USB3 ports */ + uint16_t usb3_wake_enable_bitmap; + + /* SATA related */ + uint8_t SataMode; + uint8_t SataSalpSupport; + uint8_t SataPortsEnable[8]; + uint8_t SataPortsDevSlp[8]; + + /* Audio related */ + uint8_t PchHdaDspEnable; + uint8_t PchHdaAudioLinkHdaEnable; + uint8_t PchHdaAudioLinkDmicEnable[MAX_HD_AUDIO_DMIC_LINKS]; + uint8_t PchHdaAudioLinkSspEnable[MAX_HD_AUDIO_SSP_LINKS]; + uint8_t PchHdaAudioLinkSndwEnable[MAX_HD_AUDIO_SNDW_LINKS]; + uint8_t PchHdaIDispLinkTmode; + uint8_t PchHdaIDispLinkFrequency; + uint8_t PchHdaIDispCodecDisconnect; + + /* PCIe Root Ports */ + uint8_t PcieRpEnable[CONFIG_MAX_ROOT_PORTS]; + /* PCIe output clocks type to PCIe devices. + * 0-23: PCH rootport, 0x70: LAN, 0x80: unspecified but in use, + * 0xFF: not used */ + uint8_t PcieClkSrcUsage[CONFIG_MAX_PCIE_CLOCKS]; + /* PCIe ClkReq-to-ClkSrc mapping, number of clkreq signal assigned to + * clksrc. */ + uint8_t PcieClkSrcClkReq[CONFIG_MAX_PCIE_CLOCKS]; + + /* Probe CLKREQ# signal before enabling CLKREQ# based power management.*/ + uint8_t PcieRpClkReqDetect[CONFIG_MAX_ROOT_PORTS]; + + /* PCIe RP L1 substate */ + enum L1_substates_control { + L1_SS_FSP_DEFAULT, + L1_SS_DISABLED, + L1_SS_L1_1, + L1_SS_L1_2, + } PcieRpL1Substates[CONFIG_MAX_ROOT_PORTS]; + + /* SMBus */ + uint8_t SmbusEnable; + + /* eMMC and SD */ + uint8_t ScsEmmcHs400Enabled; + + /* Enable if SD Card Power Enable Signal is Active High */ + uint8_t SdCardPowerEnableActiveHigh; + + /* Integrated Sensor */ + uint8_t PchIshEnable; + + /* Heci related */ + uint8_t Heci3Enabled; + + /* Gfx related */ + uint8_t IgdDvmt50PreAlloc; + uint8_t InternalGfx; + uint8_t SkipExtGfxScan; + + uint32_t GraphicsConfigPtr; + uint8_t Device4Enable; + + /* 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; + /* Intel Speed Shift Technology */ + uint8_t speed_shift_enable; + + /* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */ + uint8_t eist_enable; + + /* Enable C6 DRAM */ + uint8_t enable_c6dram; + /* + * PRMRR size setting with below options + * Disable: 0x0 + * 32MB: 0x2000000 + * 64MB: 0x4000000 + * 128 MB: 0x8000000 + * 256 MB: 0x10000000 + * 512 MB: 0x20000000 + */ + uint32_t PrmrrSize; + 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]; + + /* + * TraceHubMode config + * 0: Disable, 1: Target Debugger Mode, 2: Host Debugger Mode + */ + uint8_t TraceHubMode; + + /* Debug interface selection */ + enum { + DEBUG_INTERFACE_RAM = (1 << 0), + DEBUG_INTERFACE_UART_8250IO = (1 << 1), + DEBUG_INTERFACE_USB3 = (1 << 3), + DEBUG_INTERFACE_LPSS_SERIAL_IO = (1 << 4), + DEBUG_INTERFACE_TRACEHUB = (1 << 5), + } debug_interface_flag; + + /* GPIO SD card detect pin */ + unsigned int sdcard_cd_gpio; + + /* CNVi BT Audio Offload: Enable/Disable BT Audio Offload. */ + enum { + FORCE_DISABLE, + FORCE_ENABLE, + } CnviBtAudioOffload; + + /* Tcss */ + uint8_t TcssXhciEn; + uint8_t TcssXdciEn; + + /* + * Override GPIO PM configuration: + * 0: Use FSP default GPIO PM program, + * 1: coreboot to override GPIO PM program + */ + uint8_t gpio_override_pm; + + /* + * GPIO PM configuration: 0 to disable, 1 to enable power gating + * Bit 6-7: Reserved + * Bit 5: MISCCFG_GPSIDEDPCGEN + * Bit 4: MISCCFG_GPRCOMPCDLCGEN + * Bit 3: MISCCFG_GPRTCDLCGEN + * Bit 2: MISCCFG_GSXLCGEN + * Bit 1: MISCCFG_GPDPCGEN + * Bit 0: MISCCFG_GPDLCGEN + */ + uint8_t gpio_pm[TOTAL_GPIO_COMM]; + + /* DP config */ + /* + * Port config + * 0:Disabled, 1:eDP, 2:MIPI DSI + */ + uint8_t DdiPortAConfig; + uint8_t DdiPortBConfig; + + /* Enable(1)/Disable(0) HPD */ + uint8_t DdiPortAHpd; + uint8_t DdiPortBHpd; + uint8_t DdiPortCHpd; + uint8_t DdiPort1Hpd; + uint8_t DdiPort2Hpd; + uint8_t DdiPort3Hpd; + uint8_t DdiPort4Hpd; + + /* Enable(1)/Disable(0) DDC */ + uint8_t DdiPortADdc; + uint8_t DdiPortBDdc; + uint8_t DdiPortCDdc; + uint8_t DdiPort1Ddc; + uint8_t DdiPort2Ddc; + uint8_t DdiPort3Ddc; + uint8_t DdiPort4Ddc; + + /* 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. + * Valid Range 0 to 63. + * In general descriptor provides option to set default cpu flex ratio. + * Default cpu flex ratio 0 ensures booting with non-turbo max frequency. + * That's the reason FSP skips cpu_ratio override if cpu_ratio is 0. + * Only override CPU flex ratio to not boot with non-turbo max. + */ + uint8_t cpu_ratio_override; + + /* Skip CPU replacement check + * 0: disable + * 1: enable + * Setting this option to skip CPU replacement check to avoid the forced MRC training + * for the platforms with soldered down SOC. + */ + uint8_t SkipCpuReplacementCheck; + + /* + * SLP_S3 Minimum Assertion Width Policy + * 1 = 60us + * 2 = 1ms + * 3 = 50ms (default) + * 4 = 2s + */ + uint8_t PchPmSlpS3MinAssert; + + /* + * SLP_S4 Minimum Assertion Width Policy + * 1 = 1s (default) + * 2 = 2s + * 3 = 3s + * 4 = 4s + */ + uint8_t PchPmSlpS4MinAssert; + + /* + * SLP_SUS Minimum Assertion Width Policy + * 1 = 0ms + * 2 = 500ms + * 3 = 1s + * 4 = 4s (default) + */ + uint8_t PchPmSlpSusMinAssert; + + /* + * SLP_A Minimum Assertion Width Policy + * 1 = 0ms + * 2 = 4s + * 3 = 98ms + * 4 = 2s (default) + */ + uint8_t PchPmSlpAMinAssert; + + /* + * PCH PM Reset Power Cycle Duration + * 0 = 4s (default) + * 1 = 1s + * 2 = 2s + * 3 = 3s + * 4 = 4s + * + * NOTE: Duration programmed in the PchPmPwrCycDur should never be smaller than the + * stretch duration programmed in the following registers: + * - GEN_PMCON_A.SLP_S3_MIN_ASST_WDTH (PchPmSlpS3MinAssert) + * - GEN_PMCON_A.S4MAW (PchPmSlpS4MinAssert) + * - PM_CFG.SLP_A_MIN_ASST_WDTH (PchPmSlpAMinAssert) + * - PM_CFG.SLP_LAN_MIN_ASST_WDTH + */ + uint8_t PchPmPwrCycDur; +}; + +typedef struct soc_intel_elkhartlake_config config_t; + +#endif diff --git a/src/soc/intel/elkhartlake/cpu.c b/src/soc/intel/elkhartlake/cpu.c new file mode 100644 index 0000000000..382bbf7b01 --- /dev/null +++ b/src/soc/intel/elkhartlake/cpu.c @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/cpu.h> +#include <console/console.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/cpulib.h> +#include <intelblocks/mp_init.h> +#include <intelblocks/msr.h> +#include <romstage_handoff.h> +#include <soc/cpu.h> +#include <soc/msr.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> +#include <soc/soc_chip.h> + +static void soc_fsp_load(void) +{ + fsps_load(romstage_handoff_is_resume()); +} + +static void configure_isst(void) +{ + config_t *conf = config_of_soc(); + msr_t msr; + + if (conf->speed_shift_enable) { + /* + * Kernel driver checks CPUID.06h:EAX[Bit 7] to determine if HWP + * is supported or not. coreboot needs to configure MSR 0x1AA + * which is then reflected in the CPUID register. + */ + msr = rdmsr(MSR_MISC_PWR_MGMT); + msr.lo |= MISC_PWR_MGMT_ISST_EN; /* Enable Speed Shift */ + msr.lo |= MISC_PWR_MGMT_ISST_EN_INT; /* Enable Interrupt */ + msr.lo |= MISC_PWR_MGMT_ISST_EN_EPP; /* Enable EPP */ + wrmsr(MSR_MISC_PWR_MGMT, msr); + } else { + msr = rdmsr(MSR_MISC_PWR_MGMT); + msr.lo &= ~MISC_PWR_MGMT_ISST_EN; /* Disable Speed Shift */ + msr.lo &= ~MISC_PWR_MGMT_ISST_EN_INT; /* Disable Interrupt */ + msr.lo &= ~MISC_PWR_MGMT_ISST_EN_EPP; /* Disable EPP */ + wrmsr(MSR_MISC_PWR_MGMT, msr); + } +} + +static void configure_misc(void) +{ + msr_t msr; + + config_t *conf = 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); +} + +static void enable_lapic_tpr(void) +{ + msr_t msr; + + msr = rdmsr(MSR_PIC_MSG_CONTROL); + msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */ + wrmsr(MSR_PIC_MSG_CONTROL, msr); +} + +static void configure_dca_cap(void) +{ + uint32_t feature_flag; + msr_t msr; + + /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */ + feature_flag = cpu_get_feature_flags_ecx(); + if (feature_flag & CPUID_DCA) { + msr = rdmsr(IA32_PLATFORM_DCA_CAP); + msr.lo |= 1; + wrmsr(IA32_PLATFORM_DCA_CAP, msr); + } +} + +static void enable_pm_timer_emulation(void) +{ + /* ACPI PM timer emulation */ + msr_t msr; + /* + * The derived frequency is calculated as follows: + * (CTC_FREQ * msr[63:32]) >> 32 = target frequency. + * Back solve the multiplier so the 3.579545MHz ACPI timer + * frequency is used. + */ + msr.hi = (3579545ULL << 32) / CTC_FREQ; + /* Set PM1 timer IO port and enable */ + msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) | + EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR); + wrmsr(MSR_EMULATE_PM_TIMER, msr); +} + +static void set_energy_perf_bias(u8 policy) +{ + msr_t msr; + int ecx; + + /* Determine if energy efficient policy is supported. */ + ecx = cpuid_ecx(0x6); + if (!(ecx & (1 << 3))) + return; + + /* Energy Policy is bits 3:0 */ + msr = rdmsr(IA32_ENERGY_PERF_BIAS); + msr.lo &= ~0xf; + msr.lo |= policy & 0xf; + wrmsr(IA32_ENERGY_PERF_BIAS, msr); +} + +/* 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 the local CPU apics */ + enable_lapic_tpr(); + setup_lapic(); + + /* Configure Enhanced SpeedStep and Thermal Sensors */ + configure_misc(); + + /* Configure Intel Speed Shift */ + configure_isst(); + + /* Enable PM timer emulation */ + 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(); + + /* + * Now that all APs have been relocated as well as the BSP let SMIs + * start flowing. + */ + global_smi_enable(); +} + +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(); +} diff --git a/src/soc/intel/elkhartlake/elog.c b/src/soc/intel/elkhartlake/elog.c new file mode 100644 index 0000000000..c88efc81bc --- /dev/null +++ b/src/soc/intel/elkhartlake/elog.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootstate.h> +#include <console/console.h> +#include <elog.h> +#include <intelblocks/pmclib.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> +#include <stdint.h> + +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_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 (TODO: determine wake device) */ + if (ps->pm1_sts & PCIEXPWAK_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0); + + /* PME (TODO: determine wake device) */ + if (ps->gpe0_sts[GPE_STD] & PME_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); + + /* Internal PME (TODO: determine wake device) */ + if (ps->gpe0_sts[GPE_STD] & PME_B0_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); + + /* 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(struct chipset_power_state *ps) +{ + /* Thermal Trip */ + if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP) + elog_add_event(ELOG_TYPE_THERM_TRIP); + + /* 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); +} diff --git a/src/soc/intel/elkhartlake/espi.c b/src/soc/intel/elkhartlake/espi.c new file mode 100644 index 0000000000..71339971fa --- /dev/null +++ b/src/soc/intel/elkhartlake/espi.c @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include <arch/ioapic.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <intelblocks/itss.h> +#include <intelblocks/lpc_lib.h> +#include <intelblocks/pcr.h> +#include <pc80/isa-dma.h> +#include <pc80/i8259.h> +#include <soc/espi.h> +#include <soc/iomap.h> +#include <soc/irq.h> +#include <soc/pci_devs.h> +#include <soc/pcr_ids.h> +#include <soc/soc_chip.h> + +/* +* To reserve certain memory range as reserved range for BIOS usage. +* For this SOC, the range will be from 0FC800000h till FE7FFFFFh" +*/ +static const struct lpc_mmio_range ehl_lpc_fixed_mmio_ranges[] = { + { PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE }, + { 0, 0 } +}; + +const struct lpc_mmio_range *soc_get_fixed_mmio_ranges() +{ + return ehl_lpc_fixed_mmio_ranges; +} + +void soc_get_gen_io_dec_range(const struct device *dev, uint32_t *gen_io_dec) +{ + const config_t *config = config_of(dev); + + gen_io_dec[0] = config->gen1_dec; + gen_io_dec[1] = config->gen2_dec; + gen_io_dec[2] = config->gen3_dec; + gen_io_dec[3] = config->gen4_dec; +} + +void soc_setup_dmi_pcr_io_dec(uint32_t *gen_io_dec) +{ + /* Mirror these same settings in DMI PCR */ + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR1, gen_io_dec[0]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR2, gen_io_dec[1]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR3, gen_io_dec[2]); + pcr_write32(PID_DMI, PCR_DMI_LPCLGIR4, gen_io_dec[3]); +} + +#if ENV_RAMSTAGE +static void soc_mirror_dmi_pcr_io_dec(void) +{ + struct device *dev = pcidev_on_root(PCH_DEV_SLOT_ESPI, 0); + uint32_t io_dec_arr[] = { + pci_read_config32(dev, ESPI_GEN1_DEC), + pci_read_config32(dev, ESPI_GEN2_DEC), + pci_read_config32(dev, ESPI_GEN3_DEC), + pci_read_config32(dev, ESPI_GEN4_DEC), + }; + /* Mirror these same settings in DMI PCR */ + soc_setup_dmi_pcr_io_dec(&io_dec_arr[0]); +} + +static void pch_enable_ioapic(const struct device *dev) +{ + uint32_t reg32; + /* PCH-LP has 120 redirection entries */ + const int redir_entries = 120; + + set_ioapic_id((void *)IO_APIC_ADDR, 0x02); + + /* affirm full set of redirection table entries ("write once") */ + reg32 = io_apic_read((void *)IO_APIC_ADDR, 0x01); + + reg32 &= ~0x00ff0000; + reg32 |= (redir_entries - 1) << 16; + + io_apic_write((void *)IO_APIC_ADDR, 0x01, reg32); + + /* + * Select Boot Configuration register (0x03) and + * use Processor System Bus (0x01) to deliver interrupts. + */ + io_apic_write((void *)IO_APIC_ADDR, 0x03, 0x01); +} +/* + * PIRQ[n]_ROUT[3:0] - PIRQ Routing Control + * 0x00 - 0000 = Reserved + * 0x01 - 0001 = Reserved + * 0x02 - 0010 = Reserved + * 0x03 - 0011 = IRQ3 + * 0x04 - 0100 = IRQ4 + * 0x05 - 0101 = IRQ5 + * 0x06 - 0110 = IRQ6 + * 0x07 - 0111 = IRQ7 + * 0x08 - 1000 = Reserved + * 0x09 - 1001 = IRQ9 + * 0x0A - 1010 = IRQ10 + * 0x0B - 1011 = IRQ11 + * 0x0C - 1100 = IRQ12 + * 0x0D - 1101 = Reserved + * 0x0E - 1110 = IRQ14 + * 0x0F - 1111 = IRQ15 + * PIRQ[n]_ROUT[7] - PIRQ Routing Control + * 0x80 - The PIRQ is not routed. + */ + +void soc_pch_pirq_init(const struct device *dev) +{ + struct device *irq_dev; + uint8_t pch_interrupt_routing[MAX_PXRC_CONFIG]; + + pch_interrupt_routing[0] = PCH_IRQ11; + pch_interrupt_routing[1] = PCH_IRQ10; + pch_interrupt_routing[2] = PCH_IRQ11; + pch_interrupt_routing[3] = PCH_IRQ11; + pch_interrupt_routing[4] = PCH_IRQ11; + pch_interrupt_routing[5] = PCH_IRQ11; + pch_interrupt_routing[6] = PCH_IRQ11; + pch_interrupt_routing[7] = PCH_IRQ11; + + itss_irq_init(pch_interrupt_routing); + + for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + uint8_t int_pin = 0, int_line = 0; + + if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI) + continue; + + int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + + switch (int_pin) { + case 1: /* INTA# */ + int_line = PCH_IRQ11; + break; + case 2: /* INTB# */ + int_line = PCH_IRQ10; + break; + case 3: /* INTC# */ + int_line = PCH_IRQ11; + break; + case 4: /* INTD# */ + int_line = PCH_IRQ11; + break; + } + + if (!int_line) + continue; + + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line); + } +} + +static void pch_misc_init(void) +{ + uint8_t reg8; + + /* Setup NMI on errors, disable SERR */ + reg8 = (inb(NMI_STS_CNT) & 0xf0); + outb((reg8 | (1 << 2)), NMI_STS_CNT); + + /* Disable NMI sources */ + outb((1 << 7), NMI_EN); +}; + +void lpc_soc_init(struct device *dev) +{ + /* Legacy initialization */ + isa_dma_init(); + pch_misc_init(); + + /* Enable CLKRUN_EN for power gating ESPI */ + lpc_enable_pci_clk_cntl(); + + /* Set ESPI Serial IRQ mode */ + if (CONFIG(SERIRQ_CONTINUOUS_MODE)) + lpc_set_serirq_mode(SERIRQ_CONTINUOUS); + else + lpc_set_serirq_mode(SERIRQ_QUIET); + + /* Interrupt configuration */ + pch_enable_ioapic(dev); + soc_pch_pirq_init(dev); + setup_i8259(); + i8259_configure_irq_trigger(9, 1); + soc_mirror_dmi_pcr_io_dec(); +} + +#endif diff --git a/src/soc/intel/elkhartlake/finalize.c b/src/soc/intel/elkhartlake/finalize.c new file mode 100644 index 0000000000..e9b3f21683 --- /dev/null +++ b/src/soc/intel/elkhartlake/finalize.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include <bootstate.h> +#include <console/console.h> +#include <console/post_codes.h> +#include <cpu/x86/smm.h> +#include <device/mmio.h> +#include <device/pci.h> +#include <intelblocks/lpc_lib.h> +#include <intelblocks/pcr.h> +#include <intelblocks/tco.h> +#include <intelblocks/thermal.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> + +static void pch_finalize(void) +{ + uint32_t reg32; + uint8_t *pmcbase; + config_t *config; + uint8_t reg8; + + /* TCO Lock down */ + tco_lockdown(); + + /* TODO: Add Thermal Configuration */ + + /* + * Disable ACPI PM timer based on dt policy + * + * Disabling ACPI PM timer is necessary for XTAL OSC shutdown. + * Disabling ACPI PM timer also switches off TCO + * + * SA_DEV_ROOT device is used here instead of PCH_DEV_PMC since it is + * just required to get to chip config. PCH_DEV_PMC is hidden by this + * point and hence removed from the root bus. pcidev_path_on_root thus + * returns NULL for PCH_DEV_PMC device. + */ + config = config_of_soc(); + pmcbase = pmc_mmio_regs(); + if (config->PmTimerDisabled) { + reg8 = read8(pmcbase + PCH_PWRM_ACPI_TMR_CTL); + reg8 |= (1 << 1); + write8(pmcbase + PCH_PWRM_ACPI_TMR_CTL, reg8); + } + + /* Disable XTAL shutdown qualification for low power idle. */ + if (config->s0ix_enable) { + reg32 = read32(pmcbase + CPPMVRIC); + reg32 |= XTALSDQDIS; + write32(pmcbase + CPPMVRIC, reg32); + } + + pmc_clear_pmcon_sts(); +} + +static void soc_finalize(void *unused) +{ + printk(BIOS_DEBUG, "Finalizing chipset.\n"); + + pch_finalize(); + apm_control(APM_CNT_FINALIZE); + + /* Indicate finalize step with post code */ + post_code(POST_OS_BOOT); +} + +BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL); +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, soc_finalize, NULL); diff --git a/src/soc/intel/elkhartlake/fsp_params.c b/src/soc/intel/elkhartlake/fsp_params.c new file mode 100644 index 0000000000..3d740fb74c --- /dev/null +++ b/src/soc/intel/elkhartlake/fsp_params.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <assert.h> +#include <console/console.h> +#include <device/device.h> +#include <fsp/api.h> +#include <fsp/ppi/mp_service_ppi.h> +#include <fsp/util.h> +#include <intelblocks/lpss.h> +#include <intelblocks/mp_init.h> +#include <intelblocks/xdci.h> +#include <intelpch/lockdown.h> +#include <soc/intel/common/vbt.h> +#include <soc/pci_devs.h> +#include <soc/ramstage.h> +#include <soc/soc_chip.h> +#include <string.h> + +/* + * 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 { + EOP_DISABLE, + EOP_PEI, + EOP_DXE, +} EndOfPost; + +static const pci_devfn_t serial_io_dev[] = { + PCH_DEVFN_I2C0, + PCH_DEVFN_I2C1, + PCH_DEVFN_I2C2, + PCH_DEVFN_I2C3, + PCH_DEVFN_I2C4, + PCH_DEVFN_I2C5, + PCH_DEVFN_GSPI0, + PCH_DEVFN_GSPI1, + PCH_DEVFN_GSPI2, + PCH_DEVFN_UART0, + PCH_DEVFN_UART1, + PCH_DEVFN_UART2 +}; + +static void parse_devicetree(FSP_S_CONFIG *params) +{ + const struct soc_intel_elkhartlake_config *config = config_of_soc(); + /* TODO: Update with UPD override as FSP matures */ +} + +/* UPD parameters to be initialized before SiliconInit */ +void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) +{ + unsigned int i; + struct device *dev; + FSP_S_CONFIG *params = &supd->FspsConfig; + struct soc_intel_elkhartlake_config *config = config_of_soc(); + + /* Parse device tree and fill in FSP UPDs */ + parse_devicetree(params); + + /* TODO: Update with UPD override as FSP matures */ + + /* Override/Fill FSP Silicon Param for mainboard */ + mainboard_silicon_init_params(params); +} + +/* Mainboard GPIO Configuration */ +__weak void mainboard_silicon_init_params(FSP_S_CONFIG *params) +{ + printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__); +} + +/* Return list of SOC LPSS controllers */ +const pci_devfn_t *soc_lpss_controllers_list(size_t *size) +{ + *size = ARRAY_SIZE(serial_io_dev); + return serial_io_dev; +} diff --git a/src/soc/intel/elkhartlake/gpio.c b/src/soc/intel/elkhartlake/gpio.c new file mode 100644 index 0000000000..9ba5d8e058 --- /dev/null +++ b/src/soc/intel/elkhartlake/gpio.c @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <intelblocks/gpio.h> +#include <intelblocks/pcr.h> +#include <soc/pcr_ids.h> +#include <soc/pmc.h> + +static const struct reset_mapping rst_map[] = { + { .logical = PAD_CFG0_LOGICAL_RESET_RSMRST, .chipset = 0U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 }, +}; + +static const struct reset_mapping rst_map_com0[] = { + { .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_RSMRST, .chipset = 3U << 30 }, +}; + +/* + * The GPIO driver for Elkhartlake on Windows/Linux expects 32 GPIOs per pad + * group, regardless of whether or not there is a physical pad for each + * exposed GPIO number. + * + * This results in the OS having a sparse GPIO map, and devices that need + * to export an ACPI GPIO must use the OS expected number. + * + * Not all pins are usable as GPIO and those groups do not have a pad base. + * + * This layout matches the Linux kernel pinctrl map for MCC at: + * linux/drivers/pinctrl/intel/pinctrl-elkhartlake.c + */ +static const struct pad_group ehl_community0_groups[] = { + + INTEL_GPP_BASE(GPP_F0, GPP_F0, GPP_F19, 0), /* GPP_F */ + INTEL_GPP(GPP_F0, GPIO_RSVD_0, GPIO_RSVD_8), + INTEL_GPP_BASE(GPP_F0, GPP_B0, GPP_B23, 32), /* GPP_B */ + INTEL_GPP(GPP_F0, GPIO_RSVD_9, GPIO_RSVD_10), + INTEL_GPP_BASE(GPP_F0, GPP_A0, GPIO_RSVD_11, 64), /* GPP_A */ + INTEL_GPP_BASE(GPP_F0, GPP_S0, GPP_S7, 96), /* GPP_S */ + INTEL_GPP_BASE(GPP_F0, GPP_R0, GPP_R7, 128), /* GPP_R */ +}; + +static const struct pad_group ehl_community1_groups[] = { + INTEL_GPP_BASE(GPP_H0, GPP_H0, GPP_H23, 160), /* GPP_H */ + INTEL_GPP_BASE(GPP_H0, GPP_D0, GPP_D23, 192), /* GPP_D */ + INTEL_GPP(GPP_H0, GPIO_RSVD_12, GPIO_RSVD_13), + INTEL_GPP_BASE(GPP_H0, VGPIO_0, VGPIO_39, 224), /* VGPIO */ + INTEL_GPP_BASE(GPP_H0, GPP_C0, GPP_C23, 256), /* GPP_C */ +}; + +/* This community is not visible to the OS */ +static const struct pad_group ehl_community2_groups[] = { + INTEL_GPP(GPD0, GPD0, GPD10), /* GPD */ + INTEL_GPP(GPD0, GPIO_RSVD_14, GPIO_RSVD_17), +}; + + +static const struct pad_group ehl_community4_groups[] = { + INTEL_GPP(GPIO_RSVD_18, GPIO_RSVD_18, GPIO_RSVD_23), + INTEL_GPP_BASE(GPIO_RSVD_18, GPP_E0, GPP_E23, 288), /* GPP_E */ + INTEL_GPP(GPIO_RSVD_18, GPIO_RSVD_24, GPIO_RSVD_36), +}; + + +static const struct pad_group ehl_community5_groups[] = { + INTEL_GPP_BASE(GPP_G0, GPP_G0, GPP_G7, 320), /* GPP_G */ +}; + +static const struct pad_community ehl_communities[TOTAL_GPIO_COMM] = { + /* GPP F, B, A, S, R */ + [COMM_0] = { + .port = PID_GPIOCOM0, + .first_pad = GPP_F0, + .last_pad = GPP_R7, + .num_gpi_regs = NUM_GPIO_COM0_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPP_FBASR", + .acpi_path = "\\_SB.PCI0.GPIO", + .reset_map = rst_map_com0, + .num_reset_vals = ARRAY_SIZE(rst_map_com0), + .groups = ehl_community0_groups, + .num_groups = ARRAY_SIZE(ehl_community0_groups), + }, + /* GPP H, D, VGPIO, C */ + [COMM_1] = { + .port = PID_GPIOCOM1, + .first_pad = GPP_H0, + .last_pad = GPP_C23, + .num_gpi_regs = NUM_GPIO_COM1_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPP_HDC", + .acpi_path = "\\_SB.PCI0.GPIO", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = ehl_community1_groups, + .num_groups = ARRAY_SIZE(ehl_community1_groups), + }, + /* GPD */ + [COMM_2] = { + .port = PID_GPIOCOM2, + .first_pad = GPD0, + .last_pad = GPIO_RSVD_17, + .num_gpi_regs = NUM_GPIO_COM2_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPD", + .acpi_path = "\\_SB.PCI0.GPIO", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = ehl_community2_groups, + .num_groups = ARRAY_SIZE(ehl_community2_groups), + }, + /* GPP E */ + [COMM_4] = { + .port = PID_GPIOCOM4, + .first_pad = GPIO_RSVD_18, + .last_pad = GPIO_RSVD_36, + .num_gpi_regs = NUM_GPIO_COM4_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPP_E", + .acpi_path = "\\_SB.PCI0.GPIO", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = ehl_community4_groups, + .num_groups = ARRAY_SIZE(ehl_community4_groups), + }, + /* GPP G */ + [COMM_5] = { + .port = PID_GPIOCOM5, + .first_pad = GPP_G0, + .last_pad = GPP_G7, + .num_gpi_regs = NUM_GPIO_COM5_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPP_G", + .acpi_path = "\\_SB.PCI0.GPIO", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = ehl_community5_groups, + .num_groups = ARRAY_SIZE(ehl_community5_groups), + } +}; + +const struct pad_community *soc_gpio_get_community(size_t *num_communities) +{ + *num_communities = ARRAY_SIZE(ehl_communities); + return ehl_communities; +} + +const struct pmc_to_gpio_route *soc_pmc_gpio_routes(size_t *num) +{ + static const struct pmc_to_gpio_route routes[] = { + { PMC_GPP_A, GPP_A }, + { PMC_GPP_B, GPP_B }, + { PMC_GPP_G, GPP_G }, + { PMC_GPP_C, GPP_C }, + { PMC_GPP_R, GPP_R }, + { PMC_GPP_D, GPP_D }, + { PMC_GPP_S, GPP_S }, + { PMC_GPP_H, GPP_H }, + { PMC_GPP_F, GPP_F }, + { PMC_GPD, GPP_GPD }, + { PMC_GPP_E, GPP_E } + }; + + *num = ARRAY_SIZE(routes); + return routes; +} diff --git a/src/soc/intel/elkhartlake/gspi.c b/src/soc/intel/elkhartlake/gspi.c new file mode 100644 index 0000000000..61ad2608db --- /dev/null +++ b/src/soc/intel/elkhartlake/gspi.c @@ -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 PCH_DEVFN_GSPI0; + case 1: + return PCH_DEVFN_GSPI1; + case 2: + return PCH_DEVFN_GSPI2; + } + return -1; +} diff --git a/src/soc/intel/elkhartlake/i2c.c b/src/soc/intel/elkhartlake/i2c.c new file mode 100644 index 0000000000..c13a1a6099 --- /dev/null +++ b/src/soc/intel/elkhartlake/i2c.c @@ -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 PCH_DEVFN_I2C0: + return 0; + case PCH_DEVFN_I2C1: + return 1; + case PCH_DEVFN_I2C2: + return 2; + case PCH_DEVFN_I2C3: + return 3; + case PCH_DEVFN_I2C4: + return 4; + case PCH_DEVFN_I2C5: + return 5; + } + return -1; +} + +int dw_i2c_soc_bus_to_devfn(unsigned int bus) +{ + switch (bus) { + case 0: + return PCH_DEVFN_I2C0; + case 1: + return PCH_DEVFN_I2C1; + case 2: + return PCH_DEVFN_I2C2; + case 3: + return PCH_DEVFN_I2C3; + case 4: + return PCH_DEVFN_I2C4; + case 5: + return PCH_DEVFN_I2C5; + } + return -1; +} diff --git a/src/soc/intel/elkhartlake/include/soc/cpu.h b/src/soc/intel/elkhartlake/include/soc/cpu.h new file mode 100644 index 0000000000..6ee34f234c --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/cpu.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_CPU_H_ +#define _SOC_ELKHARTLAKE_CPU_H_ + +#include <intelblocks/msr.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 + +/* Common Timer Copy (CTC) frequency - 38.4MHz. */ +#define CTC_FREQ 38400000 + +#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \ + (((1 << ((base)*5)) * (limit)) / 1000) +#define C_STATE_LATENCY_FROM_LAT_REG(reg) \ + C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \ + (IRTL_1024_NS >> 10)) + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/espi.h b/src/soc/intel/elkhartlake/include/soc/espi.h index 80b5c1e49e..6c2615816e 100644 --- a/src/soc/intel/elkhartlake/include/soc/espi.h +++ b/src/soc/intel/elkhartlake/include/soc/espi.h @@ -15,14 +15,16 @@ #define SCIS_IRQ23 7 #define SERIRQ_CNTL 0x64 #define ESPI_IO_DEC 0x80 /* IO Decode Ranges Register */ -#define COMA_RANGE 0x0 /* 0x3F8 - 0x3FF COM1*/ -#define COMB_RANGE 0x1 /* 0x2F8 - 0x2FF COM2*/ +#define COMA_RANGE 0x0 /* 0x3F8 - 0x3FF COM1*/ +#define COMB_RANGE 0x1 /* 0x2F8 - 0x2FF COM2*/ #define ESPI_GEN1_DEC 0x84 /* ESPI IF Generic Decode Range 1 */ #define ESPI_GEN2_DEC 0x88 /* ESPI IF Generic Decode Range 2 */ #define ESPI_GEN3_DEC 0x8c /* ESPI IF Generic Decode Range 3 */ #define ESPI_GEN4_DEC 0x90 /* ESPI IF Generic Decode Range 4 */ #define LGMR 0x98 /* ESPI Generic Memory Range */ +#define NMI_EN 0x70 +#define NMI_STS_CNT 0x61 #define PCCTL 0xE0 /* PCI Clock Control */ -#define CLKRUN_EN (1 << 0) +#define CLKRUN_EN (1 << 0) #endif diff --git a/src/soc/intel/elkhartlake/include/soc/gpe.h b/src/soc/intel/elkhartlake/include/soc/gpe.h new file mode 100644 index 0000000000..34dfcea763 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/gpe.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_GPE_H_ +#define _SOC_GPE_H_ + +/* GPE_31_0 */ +#define GPE0_DW0_00 0 +#define GPE0_DW0_01 1 +#define GPE0_DW0_02 2 +#define GPE0_DW0_03 3 +#define GPE0_DW0_04 4 +#define GPE0_DW0_05 5 +#define GPE0_DW0_06 6 +#define GPE0_DW0_07 7 +#define GPE0_DW0_08 8 +#define GPE0_DW0_09 9 +#define GPE0_DW0_10 10 +#define GPE0_DW0_11 11 +#define GPE0_DW0_12 12 +#define GPE0_DW0_13 13 +#define GPE0_DW0_14 14 +#define GPE0_DW0_15 15 +#define GPE0_DW0_16 16 +#define GPE0_DW0_17 17 +#define GPE0_DW0_18 18 +#define GPE0_DW0_19 19 +#define GPE0_DW0_20 20 +#define GPE0_DW0_21 21 +#define GPE0_DW0_22 22 +#define GPE0_DW0_23 23 +#define GPE0_DW0_24 24 +#define GPE0_DW0_25 25 +#define GPE0_DW0_26 26 +#define GPE0_DW0_27 27 +#define GPE0_DW0_28 28 +#define GPE0_DW0_29 29 +#define GPE0_DW0_30 30 +#define GPE0_DW0_31 31 +/* GPE_63_32 */ +#define GPE0_DW1_00 32 +#define GPE0_DW1_01 33 +#define GPE0_DW1_02 34 +#define GPE0_DW1_03 36 +#define GPE0_DW1_04 36 +#define GPE0_DW1_05 37 +#define GPE0_DW1_06 38 +#define GPE0_DW1_07 39 +#define GPE0_DW1_08 40 +#define GPE0_DW1_09 41 +#define GPE0_DW1_10 42 +#define GPE0_DW1_11 43 +#define GPE0_DW1_12 44 +#define GPE0_DW1_13 45 +#define GPE0_DW1_14 46 +#define GPE0_DW1_15 47 +#define GPE0_DW1_16 48 +#define GPE0_DW1_17 49 +#define GPE0_DW1_18 50 +#define GPE0_DW1_19 51 +#define GPE0_DW1_20 52 +#define GPE0_DW1_21 53 +#define GPE0_DW1_22 54 +#define GPE0_DW1_23 55 +#define GPE0_DW1_24 56 +#define GPE0_DW1_25 57 +#define GPE0_DW1_26 58 +#define GPE0_DW1_27 59 +#define GPE0_DW1_28 60 +#define GPE0_DW1_29 61 +#define GPE0_DW1_30 62 +#define GPE0_DW1_31 63 +/* GPE_95_64 */ +#define GPE0_DW2_00 64 +#define GPE0_DW2_01 65 +#define GPE0_DW2_02 66 +#define GPE0_DW2_03 67 +#define GPE0_DW2_04 68 +#define GPE0_DW2_05 69 +#define GPE0_DW2_06 70 +#define GPE0_DW2_07 71 +#define GPE0_DW2_08 72 +#define GPE0_DW2_09 73 +#define GPE0_DW2_10 74 +#define GPE0_DW2_11 75 +#define GPE0_DW2_12 76 +#define GPE0_DW2_13 77 +#define GPE0_DW2_14 78 +#define GPE0_DW2_15 79 +#define GPE0_DW2_16 80 +#define GPE0_DW2_17 81 +#define GPE0_DW2_18 82 +#define GPE0_DW2_19 83 +#define GPE0_DW2_20 84 +#define GPE0_DW2_21 85 +#define GPE0_DW2_22 86 +#define GPE0_DW2_23 87 +#define GPE0_DW2_24 88 +#define GPE0_DW2_25 89 +#define GPE0_DW2_26 90 +#define GPE0_DW2_27 91 +#define GPE0_DW2_28 92 +#define GPE0_DW2_29 93 +#define GPE0_DW2_30 94 +#define GPE0_DW2_31 95 +/* GPE_STD */ +#define GPE0_HOT_PLUG 97 +#define GPE0_SWGPE 98 +#define GPE0_TCOSCI 102 +#define GPE0_SMB_WAK 103 +#define GPE0_PCI_EXP 105 +#define GPE0_BATLOW 106 +#define GPE0_PME 107 +#define GPE0_ME_SCI 108 +#define GPE0_PME_B0 109 +#define GPE0_ESPI 110 +#define GPE0_GPIO_T2 111 +#define GPE0_LAN_WAK 112 +#define GPE0_WADT 114 + +#define GPE_MAX GPE0_WADT +#endif /* _SOC_GPE_H_ */ diff --git a/src/soc/intel/elkhartlake/include/soc/gpio.h b/src/soc/intel/elkhartlake/include/soc/gpio.h new file mode 100644 index 0000000000..6cca742614 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/gpio.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_GPIO_H_ +#define _SOC_ELKHARTLAKE_GPIO_H_ + +#include <intelblocks/gpio.h> +#include <soc/gpio_defs.h> + +#define CROS_GPIO_NAME "INT34C8" +#define CROS_GPIO_COMM0_NAME "INT34C8:00" +#define CROS_GPIO_COMM1_NAME "INT34C8:01" +#define CROS_GPIO_COMM4_NAME "INT34C8:02" +#define CROS_GPIO_COMM5_NAME "INT34C8:03" + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/gpio_defs.h b/src/soc/intel/elkhartlake/include/soc/gpio_defs.h new file mode 100644 index 0000000000..0b8d8a74a9 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/gpio_defs.h @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_GPIO_DEFS_H_ +#define _SOC_ELKHARTLAKE_GPIO_DEFS_H_ + +#ifndef __ACPI__ +#include <stddef.h> +#endif +#include <soc/gpio_soc_defs.h> + + +#define GPIO_NUM_PAD_CFG_REGS 4 /* DW0, DW1, DW2, DW3 */ + +#define NUM_GPIO_COMx_GPI_REGS(n) \ + (ALIGN_UP((n), GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP) + +#define NUM_GPIO_COM0_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM0_PADS) +#define NUM_GPIO_COM1_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM1_PADS) +#define NUM_GPIO_COM2_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM2_PADS) +#define NUM_GPIO_COM4_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM4_PADS) +#define NUM_GPIO_COM5_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM5_PADS) + +#define NUM_GPI_STATUS_REGS \ + ((NUM_GPIO_COM0_GPI_REGS) +\ + (NUM_GPIO_COM1_GPI_REGS) +\ + (NUM_GPIO_COM2_GPI_REGS) +\ + (NUM_GPIO_COM4_GPI_REGS) +\ + (NUM_GPIO_COM5_GPI_REGS)) +/* + * IOxAPIC IRQs for the GPIOs + */ + +/* Group F */ +#define GPP_F0_IRQ 0x40 +#define GPP_F1_IRQ 0x41 +#define GPP_F2_IRQ 0x42 +#define GPP_F3_IRQ 0x43 +#define GPP_F4_IRQ 0x44 +#define GPP_F5_IRQ 0x45 +#define GPP_F6_IRQ 0x46 +#define GPP_F7_IRQ 0x47 +#define GPP_F8_IRQ 0x48 +#define GPP_F9_IRQ 0x49 +#define GPP_F10_IRQ 0x4a +#define GPP_F11_IRQ 0x4b +#define GPP_F12_IRQ 0x4c +#define GPP_F13_IRQ 0x4d +#define GPP_F14_IRQ 0x4e +#define GPP_F15_IRQ 0x4f +#define GPP_F16_IRQ 0x50 +#define GPP_F17_IRQ 0x51 +#define GPP_F18_IRQ 0x52 +#define GPP_F19_IRQ 0x53 + +/* Group G */ +#define GPP_G0_IRQ 0x18 +#define GPP_G1_IRQ 0x19 +#define GPP_G2_IRQ 0x1a +#define GPP_G3_IRQ 0x1b +#define GPP_G4_IRQ 0x1c +#define GPP_G5_IRQ 0x1d +#define GPP_G6_IRQ 0x1e +#define GPP_G7_IRQ 0x1f + +/* Group B */ +#define GPP_B0_IRQ 0x20 +#define GPP_B1_IRQ 0x21 +#define GPP_B2_IRQ 0x22 +#define GPP_B3_IRQ 0x23 +#define GPP_B4_IRQ 0x24 +#define GPP_B5_IRQ 0x25 +#define GPP_B6_IRQ 0x26 +#define GPP_B7_IRQ 0x27 +#define GPP_B8_IRQ 0x28 +#define GPP_B9_IRQ 0x29 +#define GPP_B10_IRQ 0x2a +#define GPP_B11_IRQ 0x2b +#define GPP_B12_IRQ 0x2c +#define GPP_B13_IRQ 0x2d +#define GPP_B14_IRQ 0x2e +#define GPP_B15_IRQ 0x2f +#define GPP_B16_IRQ 0x30 +#define GPP_B17_IRQ 0x31 +#define GPP_B18_IRQ 0x32 +#define GPP_B19_IRQ 0x33 +#define GPP_B20_IRQ 0x34 +#define GPP_B21_IRQ 0x35 +#define GPP_B22_IRQ 0x36 +#define GPP_B23_IRQ 0x37 + +/* Group A */ +#define GPP_A0_IRQ 0x38 +#define GPP_A1_IRQ 0x39 +#define GPP_A2_IRQ 0x3a +#define GPP_A3_IRQ 0x3b +#define GPP_A4_IRQ 0x3c +#define GPP_A5_IRQ 0x3d +#define GPP_A6_IRQ 0x3e +#define GPP_A7_IRQ 0x3f +#define GPP_A8_IRQ 0x40 +#define GPP_A9_IRQ 0x41 +#define GPP_A10_IRQ 0x42 +#define GPP_A11_IRQ 0x43 +#define GPP_A12_IRQ 0x44 +#define GPP_A13_IRQ 0x45 +#define GPP_A14_IRQ 0x46 +#define GPP_A15_IRQ 0x47 +#define GPP_A16_IRQ 0x48 +#define GPP_A17_IRQ 0x49 +#define GPP_A18_IRQ 0x4a +#define GPP_A19_IRQ 0x4b + +/* Group H */ +#define GPP_H0_IRQ 0x70 +#define GPP_H1_IRQ 0x71 +#define GPP_H2_IRQ 0x72 +#define GPP_H3_IRQ 0x73 +#define GPP_H4_IRQ 0x74 +#define GPP_H5_IRQ 0x75 +#define GPP_H6_IRQ 0x76 +#define GPP_H7_IRQ 0x77 +#define GPP_H8_IRQ 0x18 +#define GPP_H9_IRQ 0x19 +#define GPP_H10_IRQ 0x1a +#define GPP_H11_IRQ 0x1b +#define GPP_H12_IRQ 0x1c +#define GPP_H13_IRQ 0x1d +#define GPP_H14_IRQ 0x1e +#define GPP_H15_IRQ 0x1f +#define GPP_H16_IRQ 0x20 +#define GPP_H17_IRQ 0x21 +#define GPP_H18_IRQ 0x22 +#define GPP_H19_IRQ 0x23 +#define GPP_H20_IRQ 0x24 +#define GPP_H21_IRQ 0x25 +#define GPP_H22_IRQ 0x26 +#define GPP_H23_IRQ 0x27 + +/* Group D */ +#define GPP_D0_IRQ 0x28 +#define GPP_D1_IRQ 0x29 +#define GPP_D2_IRQ 0x2a +#define GPP_D3_IRQ 0x2b +#define GPP_D4_IRQ 0x2c +#define GPP_D5_IRQ 0x2d +#define GPP_D6_IRQ 0x2e +#define GPP_D7_IRQ 0x2f +#define GPP_D8_IRQ 0x30 +#define GPP_D9_IRQ 0x31 +#define GPP_D10_IRQ 0x32 +#define GPP_D11_IRQ 0x33 +#define GPP_D12_IRQ 0x34 +#define GPP_D13_IRQ 0x35 +#define GPP_D14_IRQ 0x36 +#define GPP_D15_IRQ 0x37 +#define GPP_D16_IRQ 0x38 +#define GPP_D17_IRQ 0x39 +#define GPP_D18_IRQ 0x3a +#define GPP_D19_IRQ 0x3b +#define GPP_D20_IRQ 0x3c +#define GPP_D21_IRQ 0x3d +#define GPP_D22_IRQ 0x3e +#define GPP_D23_IRQ 0x3f + +/* Group GPD */ +#define GPD0_IRQ 0x64 +#define GPD1_IRQ 0x65 +#define GPD2_IRQ 0x66 +#define GPD3_IRQ 0x67 +#define GPD4_IRQ 0x68 +#define GPD5_IRQ 0x69 +#define GPD6_IRQ 0x6a +#define GPD7_IRQ 0x6b +#define GPD8_IRQ 0x6c +#define GPD9_IRQ 0x6d +#define GPD10_IRQ 0x6e + +/* Group C */ +#define GPP_C0_IRQ 0x5a +#define GPP_C1_IRQ 0x5b +#define GPP_C2_IRQ 0x5c +#define GPP_C3_IRQ 0x5d +#define GPP_C4_IRQ 0x5e +#define GPP_C5_IRQ 0x5f +#define GPP_C6_IRQ 0x60 +#define GPP_C7_IRQ 0x61 +#define GPP_C8_IRQ 0x62 +#define GPP_C9_IRQ 0x63 +#define GPP_C10_IRQ 0x64 +#define GPP_C11_IRQ 0x65 +#define GPP_C12_IRQ 0x66 +#define GPP_C13_IRQ 0x67 +#define GPP_C14_IRQ 0x68 +#define GPP_C15_IRQ 0x69 +#define GPP_C16_IRQ 0x6a +#define GPP_C17_IRQ 0x6b +#define GPP_C18_IRQ 0x6c +#define GPP_C19_IRQ 0x6d +#define GPP_C20_IRQ 0x6e +#define GPP_C21_IRQ 0x6f +#define GPP_C22_IRQ 0x70 +#define GPP_C23_IRQ 0x71 +/* Group E */ +#define GPP_E0_IRQ 0x72 +#define GPP_E1_IRQ 0x73 +#define GPP_E2_IRQ 0x74 +#define GPP_E3_IRQ 0x75 +#define GPP_E4_IRQ 0x76 +#define GPP_E5_IRQ 0x77 +#define GPP_E6_IRQ 0x18 +#define GPP_E7_IRQ 0x19 +#define GPP_E8_IRQ 0x1a +#define GPP_E9_IRQ 0x1b +#define GPP_E10_IRQ 0x1c +#define GPP_E11_IRQ 0x1d +#define GPP_E12_IRQ 0x1e +#define GPP_E13_IRQ 0x1f +#define GPP_E14_IRQ 0x20 +#define GPP_E15_IRQ 0x21 +#define GPP_E16_IRQ 0x22 +#define GPP_E17_IRQ 0x23 +#define GPP_E18_IRQ 0x24 +#define GPP_E19_IRQ 0x25 +#define GPP_E20_IRQ 0x26 +#define GPP_E21_IRQ 0x27 +#define GPP_E22_IRQ 0x28 +#define GPP_E23_IRQ 0x29 + +/* Group R*/ +#define GPP_R0_IRQ 0x50 +#define GPP_R1_IRQ 0x51 +#define GPP_R2_IRQ 0x52 +#define GPP_R3_IRQ 0x53 +#define GPP_R4_IRQ 0x54 +#define GPP_R5_IRQ 0x55 +#define GPP_R6_IRQ 0x56 +#define GPP_R7_IRQ 0x57 + +/* Group S */ +#define GPP_S0_IRQ 0x5c +#define GPP_S1_IRQ 0x5d +#define GPP_S2_IRQ 0x5e +#define GPP_S3_IRQ 0x5f +#define GPP_S4_IRQ 0x60 +#define GPP_S5_IRQ 0x61 +#define GPP_S6_IRQ 0x62 +#define GPP_S7_IRQ 0x63 + +/* Register defines. */ +#define GPIO_MISCCFG 0x10 +#define GPE_DW_SHIFT 8 +#define GPE_DW_MASK 0xfff00 +#define HOSTSW_OWN_REG_0 0xc0 +#define GPI_INT_STS_0 0x100 +#define GPI_INT_EN_0 0x120 +#define GPI_SMI_STS_0 0x180 +#define GPI_SMI_EN_0 0x1a0 +#define PAD_CFG_BASE 0x600 + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h b/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h new file mode 100644 index 0000000000..278c2c63aa --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_GPIO_SOC_DEFS_H_ +#define _SOC_ELKHARTLAKE_GPIO_SOC_DEFS_H_ + +/* + * Most of the fixed numbers and macros are based on the GPP groups. + * The GPIO groups are accessed through register blocks called + * communities. + */ + +#define GPP_A 0x0 +#define GPP_B 0x1 +#define GPP_G 0x2 +#define GPP_C 0x3 +#define GPP_R 0x4 +#define GPP_D 0x5 +#define GPP_S 0x6 +#define GPP_H 0x7 +#define GPP_VGPIO 0x8 +#define GPP_F 0x9 +#define GPP_GPD 0xA +#define GPP_E 0xD + +#define GPIO_NUM_GROUPS 12 +#define GPIO_MAX_NUM_PER_GROUP 24 +#define SD_PWR_EN_PIN GPP_H1 + +/* + * GPIOs are ordered monotonically increasing to match ACPI/OS driver. + */ + +/* Group F */ +#define GPP_F0 0 +#define GPP_F1 1 +#define GPP_F2 2 +#define GPP_F3 3 +#define GPP_F4 4 +#define GPP_F5 5 +#define GPP_F6 6 +#define GPP_F7 7 +#define GPP_F8 8 +#define GPP_F9 9 +#define GPP_F10 10 +#define GPP_F11 11 +#define GPP_F12 12 +#define GPP_F13 13 +#define GPP_F14 14 +#define GPP_F15 15 +#define GPP_F16 16 +#define GPP_F17 17 +#define GPP_F18 18 +#define GPP_F19 19 + +/* Group B */ +#define GPIO_RSVD_0 20 +#define GPIO_RSVD_1 21 +#define GPIO_RSVD_2 22 +#define GPIO_RSVD_3 23 +#define GPIO_RSVD_4 24 +#define GPIO_RSVD_5 25 +#define GPIO_RSVD_6 26 +#define GPIO_RSVD_7 27 +#define GPIO_RSVD_8 28 +#define GPP_B0 29 +#define GPP_B1 30 +#define GPP_B2 31 +#define GPP_B3 32 +#define GPP_B4 33 +#define GPP_B5 34 +#define GPP_B6 35 +#define GPP_B7 36 +#define GPP_B8 37 +#define GPP_B9 38 +#define GPP_B10 39 +#define GPP_B11 40 +#define GPP_B12 41 +#define GPP_B13 42 +#define GPP_B14 43 +#define GPP_B15 44 +#define GPP_B16 45 +#define GPP_B17 46 +#define GPP_B18 47 +#define GPP_B19 48 +#define GPP_B20 49 +#define GPP_B21 50 +#define GPP_B22 51 +#define GPP_B23 52 +#define GPIO_RSVD_9 53 +#define GPIO_RSVD_10 54 + +/* Group A */ +#define GPP_A0 55 +#define GPP_A1 56 +#define GPP_A2 57 +#define GPP_A3 58 +#define GPP_A4 59 +#define GPP_A5 60 +#define GPP_A6 61 +#define GPP_A7 62 +#define GPP_A8 63 +#define GPP_A9 64 +#define GPP_A10 65 +#define GPP_A11 66 +#define GPP_A12 67 +#define GPP_A13 68 +#define GPP_A14 69 +#define GPP_A15 70 +#define GPP_A16 71 +#define GPP_A17 72 +#define GPP_A18 73 +#define GPP_A19 74 +#define GPIO_RSVD_11 75 + +/* Group S */ +#define GPP_S0 76 +#define GPP_S1 77 +#define GPP_S2 78 +#define GPP_S3 79 +#define GPP_S4 80 +#define GPP_S5 81 +#define GPP_S6 82 +#define GPP_S7 83 + +/* Group R */ +#define GPP_R0 84 +#define GPP_R1 85 +#define GPP_R2 86 +#define GPP_R3 87 +#define GPP_R4 88 +#define GPP_R5 89 +#define GPP_R6 90 +#define GPP_R7 91 + +#define GPIO_COM0_START GPP_F0 +#define GPIO_COM0_END GPP_R7 +#define NUM_GPIO_COM0_PADS (GPIO_COM0_END - GPIO_COM0_START + 1) + +/* Group H */ +#define GPP_H0 92 +#define GPP_H1 93 +#define GPP_H2 94 +#define GPP_H3 95 +#define GPP_H4 96 +#define GPP_H5 97 +#define GPP_H6 98 +#define GPP_H7 99 +#define GPP_H8 100 +#define GPP_H9 101 +#define GPP_H10 102 +#define GPP_H11 103 +#define GPP_H12 104 +#define GPP_H13 105 +#define GPP_H14 106 +#define GPP_H15 107 +#define GPP_H16 108 +#define GPP_H17 109 +#define GPP_H18 110 +#define GPP_H19 111 +#define GPP_H20 112 +#define GPP_H21 113 +#define GPP_H22 114 +#define GPP_H23 115 + +/* Group D */ +#define GPP_D0 116 +#define GPP_D1 117 +#define GPP_D2 118 +#define GPP_D3 119 +#define GPP_D4 120 +#define GPP_D5 121 +#define GPP_D6 122 +#define GPP_D7 123 +#define GPP_D8 124 +#define GPP_D9 125 +#define GPP_D10 126 +#define GPP_D11 127 +#define GPP_D12 128 +#define GPP_D13 129 +#define GPP_D14 130 +#define GPP_D15 131 +#define GPP_D16 132 +#define GPP_D17 133 +#define GPP_D18 134 +#define GPP_D19 135 +#define GPP_D20 136 +#define GPP_D21 137 +#define GPP_D22 138 +#define GPP_D23 139 +#define GPIO_RSVD_12 140 +#define GPIO_RSVD_13 141 + +/* Group VGPIO */ +#define VGPIO_0 142 +#define VGPIO_3 143 +#define VGPIO_4 144 +#define VGPIO_5 145 +#define VGPIO_6 146 +#define VGPIO_7 147 +#define VGPIO_8 148 +#define VGPIO_9 149 +#define VGPIO_10 150 +#define VGPIO_11 151 +#define VGPIO_12 152 +#define VGPIO_13 153 +#define VGPIO_18 154 +#define VGPIO_19 155 +#define VGPIO_20 156 +#define VGPIO_21 157 +#define VGPIO_22 158 +#define VGPIO_23 159 +#define VGPIO_24 160 +#define VGPIO_25 161 +#define VGPIO_30 162 +#define VGPIO_31 163 +#define VGPIO_32 164 +#define VGPIO_33 165 +#define VGPIO_34 166 +#define VGPIO_35 167 +#define VGPIO_36 168 +#define VGPIO_37 169 +#define VGPIO_39 170 + +/* Group C */ +#define GPP_C0 171 +#define GPP_C1 172 +#define GPP_C2 173 +#define GPP_C3 174 +#define GPP_C4 175 +#define GPP_C5 176 +#define GPP_C6 177 +#define GPP_C7 178 +#define GPP_C8 179 +#define GPP_C9 180 +#define GPP_C10 181 +#define GPP_C11 182 +#define GPP_C12 183 +#define GPP_C13 184 +#define GPP_C14 185 +#define GPP_C15 186 +#define GPP_C16 187 +#define GPP_C17 188 +#define GPP_C18 189 +#define GPP_C19 190 +#define GPP_C20 191 +#define GPP_C21 192 +#define GPP_C22 193 +#define GPP_C23 194 + +#define GPIO_COM1_START GPP_H0 +#define GPIO_COM1_END GPP_C23 +#define NUM_GPIO_COM1_PADS (GPIO_COM1_END - GPIO_COM1_START + 1) + +/* Group GPD */ +#define GPD0 195 +#define GPD1 196 +#define GPD2 197 +#define GPD3 198 +#define GPD4 199 +#define GPD5 200 +#define GPD6 201 +#define GPD7 202 +#define GPD8 203 +#define GPD9 204 +#define GPD10 205 +#define GPIO_RSVD_14 206 +#define GPIO_RSVD_15 207 +#define GPIO_RSVD_16 208 +#define GPIO_RSVD_17 209 + +#define GPIO_COM2_START GPD0 +#define GPIO_COM2_END GPIO_RSVD_17 +#define NUM_GPIO_COM2_PADS (GPIO_COM2_END - GPIO_COM2_START + 1) + +/* Group E */ +#define GPIO_RSVD_18 210 +#define GPIO_RSVD_19 211 +#define GPIO_RSVD_20 212 +#define GPIO_RSVD_21 213 +#define GPIO_RSVD_22 214 +#define GPIO_RSVD_23 215 +#define GPP_E0 216 +#define GPP_E1 217 +#define GPP_E2 218 +#define GPP_E3 219 +#define GPP_E4 220 +#define GPP_E5 221 +#define GPP_E6 222 +#define GPP_E7 223 +#define GPP_E8 224 +#define GPP_E9 225 +#define GPP_E10 226 +#define GPP_E11 227 +#define GPP_E12 228 +#define GPP_E13 229 +#define GPP_E14 230 +#define GPP_E15 231 +#define GPP_E16 232 +#define GPP_E17 233 +#define GPP_E18 234 +#define GPP_E19 235 +#define GPP_E20 236 +#define GPP_E21 237 +#define GPP_E22 238 +#define GPP_E23 239 +#define GPIO_RSVD_24 240 +#define GPIO_RSVD_25 241 +#define GPIO_RSVD_26 242 +#define GPIO_RSVD_27 243 +#define GPIO_RSVD_28 244 +#define GPIO_RSVD_29 245 +#define GPIO_RSVD_30 246 +#define GPIO_RSVD_31 247 +#define GPIO_RSVD_32 248 +#define GPIO_RSVD_33 249 +#define GPIO_RSVD_34 250 +#define GPIO_RSVD_35 251 +#define GPIO_RSVD_36 252 + +#define GPIO_COM4_START GPIO_RSVD_18 +#define GPIO_COM4_END GPIO_RSVD_36 +#define NUM_GPIO_COM4_PADS (GPIO_COM4_END - GPIO_COM4_START + 1) + +/* Group G */ +#define GPP_G0 253 +#define GPP_G1 254 +#define GPP_G2 255 +#define GPP_G3 256 +#define GPP_G4 257 +#define GPP_G5 258 +#define GPP_G6 259 +#define GPP_G7 260 + +#define GPIO_COM5_START GPP_G0 +#define GPIO_COM5_END GPP_G7 +#define NUM_GPIO_COM5_PADS (GPIO_COM5_END - GPIO_COM5_START + 1) + +#define TOTAL_PADS 261 + +#define COMM_0 0 +#define COMM_1 1 +#define COMM_2 2 +#define COMM_4 3 +#define COMM_5 4 +#define TOTAL_GPIO_COMM 5 + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/irq.h b/src/soc/intel/elkhartlake/include/soc/irq.h new file mode 100644 index 0000000000..ac45424476 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/irq.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_EHL_IRQ_H_ +#define _SOC_EHL_IRQ_H_ + +#define GPIO_IRQ14 14 +#define GPIO_IRQ15 15 + +#define PCH_IRQ10 10 +#define PCH_IRQ11 11 + +/* LPSS Device IRQs */ +#define LPSS_I2C0_IRQ 16 +#define LPSS_I2C1_IRQ 17 +#define LPSS_I2C2_IRQ 18 +#define LPSS_I2C3_IRQ 19 +#define LPSS_I2C4_IRQ 32 +#define LPSS_I2C5_IRQ 33 +#define LPSS_SPI0_IRQ 22 +#define LPSS_SPI1_IRQ 23 +#define LPSS_SPI2_IRQ 24 +#define LPSS_UART0_IRQ 20 +#define LPSS_UART1_IRQ 21 +#define LPSS_UART2_IRQ 34 + +/* PCI shared IRQs */ +#define PCH_IRQ_16 16 +#define PCH_IRQ_17 17 +#define PCH_IRQ_18 18 +#define PCH_IRQ_19 19 +#define PCH_IRQ_20 20 +#define PCH_IRQ_21 21 +#define PCH_IRQ_22 22 +#define PCH_IRQ_23 23 + +#endif /* _EHL_IRQ_H_ */ diff --git a/src/soc/intel/elkhartlake/include/soc/itss.h b/src/soc/intel/elkhartlake/include/soc/itss.h new file mode 100644 index 0000000000..a550f4c922 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/itss.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_INTEL_EHL_ITSS_H +#define SOC_INTEL_EHL_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_EHL_ITSS_H */ diff --git a/src/soc/intel/elkhartlake/include/soc/me.h b/src/soc/intel/elkhartlake/include/soc/me.h new file mode 100644 index 0000000000..d845629e4a --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/me.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ELKHARTLAKE_ME_H_ +#define _ELKHARTLAKE_ME_H_ + +/* ME Host Firmware Status register 1 */ +union me_hfsts1 { + uint32_t data; + struct { + uint32_t working_state: 4; + uint32_t mfg_mode: 1; + uint32_t fpt_bad: 1; + uint32_t operation_state: 3; + uint32_t fw_init_complete: 1; + uint32_t ft_bup_ld_flr: 1; + uint32_t update_in_progress: 1; + uint32_t error_code: 4; + uint32_t operation_mode: 4; + uint32_t reset_count: 4; + uint32_t boot_options_present: 1; + uint32_t reserved1: 1; + uint32_t bist_test_state: 1; + uint32_t bist_reset_request: 1; + uint32_t current_power_source: 2; + uint32_t reserved: 1; + uint32_t d0i3_support_valid: 1; + } __packed fields; +}; + +/* 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; +}; + +/* ME Host Firmware Status Register 3 */ +union me_hfsts3 { + uint32_t data; + struct { + uint32_t reserved_0: 4; + uint32_t fw_sku: 3; + uint32_t reserved: 25; + } __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; +}; +#endif /* _ELKHARTLAKE_ME_H_ */ diff --git a/src/soc/intel/elkhartlake/include/soc/meminit.h b/src/soc/intel/elkhartlake/include/soc/meminit.h new file mode 100644 index 0000000000..ea4664a150 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/meminit.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_MEMINIT_H_ +#define _SOC_ELKHARTLAKE_MEMINIT_H_ + +#include <fsp/soc_binding.h> +#include <types.h> + +/* Number of dq bits controlled per dqs */ +#define DQ_BITS_PER_DQS 8 + +/* Number of memory packages, where a "package" represents a 64-bit solution */ +#define DDR_NUM_PACKAGES 2 + +/* Number of DQ byte mappings */ +#define DDR_NUM_BYTE_MAPPINGS 6 + +/* Number of memory DIMM slots available on Elkhart Lake */ +#define NUM_DIMM_SLOT 4 + +/* 64-bit Channel identification */ +enum { + DDR_CH0, + DDR_CH1, + DDR_NUM_CHANNELS +}; + +struct spd_by_pointer { + size_t spd_data_len; + uintptr_t spd_data_ptr; +}; + +enum mem_info_read_type { + READ_SPD_CBFS, /* Find SPD file in CBFS. */ + READ_SMBUS, /* Read on-module SPD by SMBUS. */ + READ_SPD_MEMPTR /* Find SPD data from pointer. */ +}; + +struct spd_info { + enum mem_info_read_type read_type; + union spd_data_by { + /* To read on-module SPD when read_type is READ_SMBUS. */ + uint8_t spd_smbus_address[NUM_DIMM_SLOT]; + + /* To identify SPD file when read_type is READ_SPD_CBFS. */ + int spd_index; + + /* To find SPD data when read_type is READ_SPD_MEMPTR. */ + struct spd_by_pointer spd_data_ptr_info; + } spd_spec; +}; + +/* Board-specific memory dq mapping information */ +struct mb_cfg { + + /* + * For each channel, there are 6 sets of DQ byte mappings, + * where each set has a package 0 and a package 1 value (package 0 + * represents the first 64-bit lpddr4 chip combination, and package 1 + * represents the second 64-bit lpddr4 chip combination). + * The first three sets are for CLK, CMD, and CTL. + * The fsp package actually expects 6 sets, even though the last 3 sets + * are not used in EHL. + * We let the meminit_dq_dqs_map routine take care of clearing the + * unused fields for the caller. + * Note that dq_map is only used by LPDDR; it does not need to be + * initialized for designs using DDR4. + */ + uint8_t dq_map[DDR_NUM_CHANNELS][DDR_NUM_BYTE_MAPPINGS][DDR_NUM_PACKAGES]; + + /* + * DQS CPU<>DRAM map Ch0 and Ch1. Each array entry represents a + * mapping of a dq bit on the CPU to the bit it's connected to on + * the memory part. The array index represents the dqs bit number + * on the memory part, and the values in the array represent which + * pin on the CPU that DRAM pin connects to. + * dqs_map is only used by LPDDR; same comments apply as for dq_map + * above. + */ + uint8_t dqs_map[DDR_NUM_CHANNELS][DQ_BITS_PER_DQS]; + + /* + * Rcomp resistor values. These values represent the resistance in + * ohms of the three rcomp resistors attached to the DDR_COMP_0, + * DDR_COMP_1, and DDR_COMP_2 pins on the DRAM. + */ + uint16_t rcomp_resistor[3]; + + /* + * Rcomp target values. These will typically be the following + * values for Elkhart Lake : { 80, 40, 40, 40, 30 } + */ + uint16_t rcomp_targets[5]; + + /* + * Early Command Training Enable/Disable Control + * 1 = enable, 0 = disable + */ + uint8_t ect; + + /* Board type */ + uint8_t UserBd; +}; + +/* + * Initialize default memory configurations for Elkhart Lake. + */ + +void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, + const struct spd_info *spd_info, bool half_populated); + +#endif /* _SOC_ELKHARTLAKE_MEMINIT_H_ */ diff --git a/src/soc/intel/elkhartlake/include/soc/msr.h b/src/soc/intel/elkhartlake/include/soc/msr.h new file mode 100644 index 0000000000..67e09dcf41 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/msr.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_MSR_H_ +#define _SOC_MSR_H_ + +#include <intelblocks/msr.h> + +#define MSR_PIC_MSG_CONTROL 0x2e +#define MSR_VR_MISC_CONFIG2 0x636 + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/nvs.h b/src/soc/intel/elkhartlake/include/soc/nvs.h new file mode 100644 index 0000000000..512945898e --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/nvs.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_NVS_H_ +#define _SOC_NVS_H_ + +#include <intelblocks/nvs.h> + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/pmc.h b/src/soc/intel/elkhartlake/include/soc/pmc.h new file mode 100644 index 0000000000..59bee8f4a3 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/pmc.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ELKHARTLAKE_PMC_H_ +#define _SOC_ELKHARTLAKE_PMC_H_ + +/* PCI Configuration Space (D31:F2): PMC */ +#define PWRMBASE 0x10 +#define ABASE 0x20 + +/* Memory mapped IO registers in PMC */ +#define GEN_PMCON_A 0x1020 +#define DC_PP_DIS (1 << 30) +#define DSX_PP_DIS (1 << 29) +#define AG3_PP_EN (1 << 28) +#define SX_PP_EN (1 << 27) +#define ALLOW_ICLK_PLL_SD_INC0 (1 << 26) +#define GBL_RST_STS (1 << 24) +#define DISB (1 << 23) +#define ALLOW_OPI_PLL_SD_INC0 (1 << 22) +#define MEM_SR (1 << 21) +#define ALLOW_SPXB_CG_INC0 (1 << 20) +#define ALLOW_L1LOW_C0 (1 << 19) +#define MS4V (1 << 18) +#define ALLOW_L1LOW_OPI_ON (1 << 17) +#define SUS_PWR_FLR (1 << 16) +#define PME_B0_S5_DIS (1 << 15) +#define PWR_FLR (1 << 14) +#define ALLOW_L1LOW_BCLKREQ_ON (1 << 13) +#define DIS_SLP_X_STRCH_SUS_UP (1 << 12) +#define SLP_S3_MIN_ASST_WDTH_MASK (3 << 10) +#define SLP_S3_MIN_ASST_WDTH_60USEC (0 << 10) +#define SLP_S3_MIN_ASST_WDTH_1MS (1 << 10) +#define SLP_S3_MIN_ASST_WDTH_50MS (2 << 10) +#define SLP_S3_MIN_ASST_WDTH_2S (3 << 10) +#define HOST_RST_STS (1 << 9) +#define ESPI_SMI_LOCK (1 << 8) +#define S4MAW_MASK (3 << 4) +#define S4MAW_1S (1 << 4) +#define S4MAW_2S (2 << 4) +#define S4MAW_3S (3 << 4) +#define S4MAW_4S (0 << 4) +#define S4ASE (1 << 3) +#define PER_SMI_SEL_MASK (3 << 1) +#define SMI_RATE_64S (0 << 1) +#define SMI_RATE_32S (1 << 1) +#define SMI_RATE_16S (2 << 1) +#define SMI_RATE_8S (3 << 1) +#define SLEEP_AFTER_POWER_FAIL (1 << 0) + +#define GEN_PMCON_B 0x1024 +#define SLP_STR_POL_LOCK (1 << 18) +#define ACPI_BASE_LOCK (1 << 17) +#define PM_DATA_BAR_DIS (1 << 16) +#define WOL_EN_OVRD (1 << 13) +#define BIOS_PCI_EXP_EN (1 << 10) +#define PWRBTN_LVL (1 << 9) +#define SMI_LOCK (1 << 4) +#define RTC_BATTERY_DEAD (1 << 2) + +#define ETR 0x1048 +#define CF9_LOCK (1 << 31) +#define CF9_GLB_RST (1 << 20) + +#define SSML 0x104C +#define SSML_SSL_DS (0 << 0) +#define SSML_SSL_EN (1 << 0) + +#define SSMC 0x1050 +#define SSMC_SSMS (1 << 0) + +#define SSMD 0x1054 +#define SSMD_SSD_MASK (0xffff << 0) + +#define PRSTS 0x1810 + +#define S3_PWRGATE_POL 0x1828 +#define S3DC_GATE_SUS (1 << 1) +#define S3AC_GATE_SUS (1 << 0) + +#define S4_PWRGATE_POL 0x182c +#define S4DC_GATE_SUS (1 << 1) +#define S4AC_GATE_SUS (1 << 0) + +#define S5_PWRGATE_POL 0x1830 +#define S5DC_GATE_SUS (1 << 15) +#define S5AC_GATE_SUS (1 << 14) + +#define DSX_CFG 0x1834 +#define REQ_CNV_NOWAKE_DSX (1 << 4) +#define REQ_BATLOW_DSX (1 << 3) +#define DSX_EN_WAKE_PIN (1 << 2) +#define DSX_DIS_AC_PRESENT_PD (1 << 1) +#define DSX_EN_LAN_WAKE_PIN (1 << 0) +#define DSX_CFG_MASK (0x1f << 0) + +#define PMSYNC_TPR_CFG 0x18C4 +#define PCH2CPU_TPR_CFG_LOCK (1 << 31) +#define PCH2CPU_TT_EN (1 << 26) + +#define PCH_PWRM_ACPI_TMR_CTL 0x18FC +#define GPIO_GPE_CFG 0x1920 +#define GPE0_DWX_MASK 0xf +#define GPE0_DW_SHIFT(x) (4*(x)) + +#define PMC_GPP_G 0x0 +#define PMC_GPP_B 0x1 +#define PMC_GPP_A 0x2 +#define PMC_GPP_R 0x3 +#define PMC_GPP_S 0x4 +#define PMC_GPD 0x5 +#define PMC_GPP_H 0x6 +#define PMC_GPP_D 0x7 +#define PMC_GPP_F 0x8 +#define PMC_GPP_C 0xA +#define PMC_GPP_E 0xB + +#define GBLRST_CAUSE0 0x1924 +#define GBLRST_CAUSE0_THERMTRIP (1 << 5) +#define GBLRST_CAUSE1 0x1928 + +#define CPPMVRIC 0x1B1C +#define XTALSDQDIS (1 << 22) + +#define IRQ_REG ACTL +#define SCI_IRQ_ADJUST 0 +#define ACTL 0x1BD8 +#define PWRM_EN (1 << 8) +#define ACPI_EN (1 << 7) +#define SCI_IRQ_SEL (7 << 0) + +#define SCIS_IRQ9 0 +#define SCIS_IRQ10 1 +#define SCIS_IRQ11 2 +#define SCIS_IRQ20 4 +#define SCIS_IRQ21 5 +#define SCIS_IRQ22 6 +#define SCIS_IRQ23 7 +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/ramstage.h b/src/soc/intel/elkhartlake/include/soc/ramstage.h new file mode 100644 index 0000000000..8188fbdb84 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/ramstage.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_RAMSTAGE_H_ +#define _SOC_RAMSTAGE_H_ + +#include <device/device.h> +#include <fsp/api.h> +#include <fsp/util.h> +#include <soc/soc_chip.h> + +void mainboard_silicon_init_params(FSP_S_CONFIG *params); +void soc_init_pre_device(void *chip_info); + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/serialio.h b/src/soc/intel/elkhartlake/include/soc/serialio.h new file mode 100644 index 0000000000..e42af5f781 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/serialio.h @@ -0,0 +1,36 @@ +/* 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, + PchSerialIoIndexGSPI3, +}; + +enum { + PchSerialIoIndexUART0, + PchSerialIoIndexUART1, + PchSerialIoIndexUART2, +}; + +#endif diff --git a/src/soc/intel/elkhartlake/include/soc/usb.h b/src/soc/intel/elkhartlake/include/soc/usb.h new file mode 100644 index 0000000000..247b0ba554 --- /dev/null +++ b/src/soc/intel/elkhartlake/include/soc/usb.h @@ -0,0 +1,139 @@ +/* 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_PRE_EMP_ON, \ + .pre_emp_bias = USB2_BIAS_56P3MV, \ + .pre_emp_bit = USB2_HALF_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, \ +} + +#endif diff --git a/src/soc/intel/elkhartlake/lockdown.c b/src/soc/intel/elkhartlake/lockdown.c new file mode 100644 index 0000000000..b2d4210531 --- /dev/null +++ b/src/soc/intel/elkhartlake/lockdown.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <device/mmio.h> +#include <intelblocks/cfg.h> +#include <intelpch/lockdown.h> +#include <soc/pm.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); +} diff --git a/src/soc/intel/elkhartlake/me.c b/src/soc/intel/elkhartlake/me.c new file mode 100644 index 0000000000..d00702eef5 --- /dev/null +++ b/src/soc/intel/elkhartlake/me.c @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootstate.h> +#include <console/console.h> +#include <intelblocks/cse.h> +#include <soc/me.h> + +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); + + printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n", + hfsts1.fields.mfg_mode ? "YES" : "NO"); + 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: 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); diff --git a/src/soc/intel/elkhartlake/meminit.c b/src/soc/intel/elkhartlake/meminit.c new file mode 100644 index 0000000000..cd777ba3a0 --- /dev/null +++ b/src/soc/intel/elkhartlake/meminit.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <console/console.h> +#include <fsp/util.h> +#include <soc/meminit.h> +#include <spd_bin.h> +#include <string.h> + +static void spd_read_from_cbfs(const struct spd_info *spd_info, uintptr_t *spd_data_ptr, + size_t *spd_data_len) +{ + struct region_device spd_rdev; + size_t spd_index = spd_info->spd_spec.spd_index; + + printk(BIOS_DEBUG, "SPD INDEX = %lu\n", spd_index); + if (get_spd_cbfs_rdev(&spd_rdev, spd_index) < 0) + die("spd.bin not found or incorrect index\n"); + + *spd_data_len = region_device_sz(&spd_rdev); + + /* Memory leak is ok since we have memory mapped boot media */ + assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED)); + + *spd_data_ptr = (uintptr_t)rdev_mmap_full(&spd_rdev); +} + +static void get_spd_data(const struct spd_info *spd_info, uintptr_t *spd_data_ptr, + size_t *spd_data_len) +{ + if (spd_info->read_type == READ_SPD_MEMPTR) { + *spd_data_ptr = spd_info->spd_spec.spd_data_ptr_info.spd_data_ptr; + *spd_data_len = spd_info->spd_spec.spd_data_ptr_info.spd_data_len; + return; + } + + if (spd_info->read_type == READ_SPD_CBFS) { + spd_read_from_cbfs(spd_info, spd_data_ptr, spd_data_len); + return; + } + + die("no valid way to read SPD info"); +} + +static void meminit_dq_dqs_map(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, + bool half_populated) +{ + memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor, + sizeof(mem_cfg->RcompResistor)); + + memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets, + sizeof(mem_cfg->RcompTarget)); + + memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[DDR_CH0], + sizeof(board_cfg->dq_map[DDR_CH0])); + + memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[DDR_CH0], + sizeof(board_cfg->dqs_map[DDR_CH0])); + + if (half_populated) + return; + + memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[DDR_CH1], + sizeof(board_cfg->dq_map[DDR_CH1])); + + memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[DDR_CH1], + sizeof(board_cfg->dqs_map[DDR_CH1])); +} + +static void meminit_channels(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, + uintptr_t spd_data_ptr, bool half_populated) +{ + /* Channel 0 */ + mem_cfg->MemorySpdPtr00 = spd_data_ptr; + mem_cfg->MemorySpdPtr01 = 0; + + if (half_populated) { + printk(BIOS_INFO, "%s: DRAM half-populated\n", __func__); + spd_data_ptr = 0; + } + + /* Channel 1 */ + mem_cfg->MemorySpdPtr10 = spd_data_ptr; + mem_cfg->MemorySpdPtr11 = 0; + + meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated); +} + +/* Initialize onboard memory configurations for lpddr4x */ +void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg, + const struct spd_info *spd_info, bool half_populated) +{ + + if (spd_info->read_type == READ_SMBUS) { + for (int i = 0; i < NUM_DIMM_SLOT; i++) + mem_cfg->SpdAddressTable[i] = spd_info->spd_spec.spd_smbus_address[i]; + + meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated); + } else { + uintptr_t spd_data_ptr = 0; + size_t spd_data_len = 0; + memset(&mem_cfg->SpdAddressTable, 0, sizeof(mem_cfg->SpdAddressTable)); + get_spd_data(spd_info, &spd_data_ptr, &spd_data_len); + print_spd_info((unsigned char *)spd_data_ptr); + + mem_cfg->MemorySpdDataLen = spd_data_len; + meminit_channels(mem_cfg, board_cfg, spd_data_ptr, half_populated); + } + + /* Early Command Training Enabled */ + mem_cfg->ECT = board_cfg->ect; + + mem_cfg->UserBd = board_cfg->UserBd; +} diff --git a/src/soc/intel/elkhartlake/p2sb.c b/src/soc/intel/elkhartlake/p2sb.c new file mode 100644 index 0000000000..0ddd007920 --- /dev/null +++ b/src/soc/intel/elkhartlake/p2sb.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <intelblocks/p2sb.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 = (1 << 29) | (1 << 28) | (1 << 27) | (1 << 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 = (1 << 31) | (1 << 30); + + ep_mask[P2SB_EP_MASK_7_REG] = mask; +} diff --git a/src/soc/intel/elkhartlake/pmc.c b/src/soc/intel/elkhartlake/pmc.c new file mode 100644 index 0000000000..57f26d921c --- /dev/null +++ b/src/soc/intel/elkhartlake/pmc.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootstate.h> +#include <console/console.h> +#include <device/device.h> +#include <device/mmio.h> +#include <intelblocks/pmc.h> +#include <intelblocks/pmclib.h> +#include <intelblocks/rtc.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> +#include <soc/soc_chip.h> + +/* + * 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); +} + +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 pmc_init(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; + + mmio_resource(dev, 0, PCH_PWRM_BASE_ADDRESS / KiB, PCH_PWRM_BASE_SIZE / KiB); + + 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_acpi_mode_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 + * EHL has its PMC device available for device_operations, it can be + * done from the "ops->init" callback. + */ + pmc_set_acpi_mode(); +} + +struct device_operations pmc_ops = { + .read_resources = soc_pmc_read_resources, + .set_resources = noop_set_resources, + .init = soc_acpi_mode_init, + .enable = pmc_init, +}; diff --git a/src/soc/intel/elkhartlake/pmutil.c b/src/soc/intel/elkhartlake/pmutil.c new file mode 100644 index 0000000000..4d5c04d02d --- /dev/null +++ b/src/soc/intel/elkhartlake/pmutil.c @@ -0,0 +1,266 @@ +/* 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 <cbmem.h> +#include <console/console.h> +#include <device/device.h> +#include <device/mmio.h> +#include <device/pci.h> +#include <device/pci_def.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> + +/* + * 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); +} + +void pmc_clear_pmcon_sts(void) +{ + uint32_t reg_val; + uint8_t *addr; + addr = pmc_mmio_regs(); + + reg_val = read32(addr + GEN_PMCON_A); + /* Clear SUS_PWR_FLR, GBL_RST_STS, HOST_RST_STS, PWR_FLR bits + * while retaining MS4V write-1-to-clear bit */ + reg_val &= ~(MS4V); + + write32((addr + GEN_PMCON_A), reg_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_elkhartlake_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 = cbmem_find(CBMEM_ID_POWER_STATE); + + if (!ps) { + printk(BIOS_ERR, "Could not find power state in cbmem, RTC init aborted\n"); + 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); + + 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]); +} + +/* STM Support */ +uint16_t get_pmbase(void) +{ + return (uint16_t) ACPI_BASE_ADDRESS; +} diff --git a/src/soc/intel/elkhartlake/reset.c b/src/soc/intel/elkhartlake/reset.c new file mode 100644 index 0000000000..107db5accb --- /dev/null +++ b/src/soc/intel/elkhartlake/reset.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cf9_reset.h> +#include <console/console.h> +#include <fsp/util.h> +#include <intelblocks/cse.h> +#include <intelblocks/pmclib.h> +#include <soc/intel/common/reset.h> +#include <soc/pci_devs.h> + +void do_global_reset(void) +{ + /* Ask CSE to do the global reset */ + if (cse_request_global_reset(GLOBAL_RESET)) + return; + + /* global reset if CSE fail to reset */ + pmc_global_reset_enable(1); + do_full_reset(); +} + +void chipset_handle_reset(uint32_t status) +{ + switch (status) { + case FSP_STATUS_RESET_REQUIRED_3: /* Global Reset */ + printk(BIOS_DEBUG, "GLOBAL RESET!!\n"); + global_reset(); + break; + default: + printk(BIOS_ERR, "unhandled reset type %x\n", status); + die("unknown reset type"); + break; + } +} diff --git a/src/soc/intel/elkhartlake/sd.c b/src/soc/intel/elkhartlake/sd.c new file mode 100644 index 0000000000..a4b89c5803 --- /dev/null +++ b/src/soc/intel/elkhartlake/sd.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <intelblocks/sd.h> +#include <soc/soc_chip.h> + +int sd_fill_soc_gpio_info(struct acpi_gpio *gpio, const struct device *dev) +{ + config_t *config = config_of(dev); + + if (!config->sdcard_cd_gpio) + return -1; + + gpio->type = ACPI_GPIO_TYPE_INTERRUPT; + gpio->pull = ACPI_GPIO_PULL_NONE; + gpio->irq.mode = ACPI_IRQ_EDGE_TRIGGERED; + gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH; + gpio->irq.shared = ACPI_IRQ_SHARED; + gpio->irq.wake = ACPI_IRQ_WAKE; + gpio->interrupt_debounce_timeout = 10000; /* 100ms */ + gpio->pin_count = 1; + gpio->pins[0] = config->sdcard_cd_gpio; + + return 0; +} diff --git a/src/soc/intel/elkhartlake/smihandler.c b/src/soc/intel/elkhartlake/smihandler.c new file mode 100644 index 0000000000..7d2a15e737 --- /dev/null +++ b/src/soc/intel/elkhartlake/smihandler.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <device/pci_def.h> +#include <intelblocks/cse.h> +#include <intelblocks/smihandler.h> +#include <soc/soc_chip.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> + +/* + * Specific SOC SMI handler during ramstage finalize phase + * + * BIOS can't make CSME function disable as is due to POSTBOOT_SAI + * restriction in place from MCC chipset. Hence create SMI Handler to + * perform CSME function disabling logic during SMM mode. + */ +void smihandler_soc_at_finalize(void) +{ + const struct soc_intel_elkhartlake_config *config; + + config = config_of_soc(); + + if (!config->HeciEnabled && CONFIG(HECI_DISABLE_USING_SMM)) + heci_disable(); +} + +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, +}; diff --git a/src/soc/intel/elkhartlake/smmrelocate.c b/src/soc/intel/elkhartlake/smmrelocate.c new file mode 100644 index 0000000000..11b631bb86 --- /dev/null +++ b/src/soc/intel/elkhartlake/smmrelocate.c @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <cpu/intel/em64t101_save_state.h> +#include <cpu/intel/smm_reloc.h> +#include <cpu/x86/mp.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/mtrr.h> +#include <cpu/x86/smm.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <smp/node.h> +#include <soc/cpu.h> +#include <soc/msr.h> +#include <soc/pci_devs.h> +#include <soc/soc_chip.h> +#include <string.h> +#include <types.h> + +static void update_save_state(int cpu, uintptr_t curr_smbase, + uintptr_t staggered_smbase, + struct smm_relocation_params *relo_params) +{ + u32 smbase; + u32 iedbase; + + /* + * The relocated handler runs with all CPUs concurrently. Therefore + * stagger the entry points adjusting SMBASE downwards by save state + * size * CPU num. + */ + smbase = staggered_smbase; + iedbase = relo_params->ied_base; + + printk(BIOS_DEBUG, "New SMBASE=0x%08x IEDBASE=0x%08x\n", + smbase, iedbase); + + /* + * All threads need to set IEDBASE and SMBASE to the relocated + * handler region. However, the save state location depends on the + * smm_save_state_in_msrs field in the relocation parameters. If + * smm_save_state_in_msrs is non-zero then the CPUs are relocating + * the SMM handler in parallel, and each CPUs save state area is + * located in their respective MSR space. If smm_save_state_in_msrs + * is zero then the SMM relocation is happening serially so the + * save state is at the same default location for all CPUs. + */ + if (relo_params->smm_save_state_in_msrs) { + msr_t smbase_msr; + msr_t iedbase_msr; + + smbase_msr.lo = smbase; + smbase_msr.hi = 0; + + /* + * According the BWG the IEDBASE MSR is in bits 63:32. It's + * not clear why it differs from the SMBASE MSR. + */ + iedbase_msr.lo = 0; + iedbase_msr.hi = iedbase; + + wrmsr(SMBASE_MSR, smbase_msr); + wrmsr(IEDBASE_MSR, iedbase_msr); + } else { + em64t101_smm_state_save_area_t *save_state; + + save_state = (void *)(curr_smbase + SMM_DEFAULT_SIZE - + sizeof(*save_state)); + + save_state->smbase = smbase; + save_state->iedbase = iedbase; + } +} + +/* Returns 1 if SMM MSR save state was set. */ +static int bsp_setup_msr_save_state(struct smm_relocation_params *relo_params) +{ + msr_t smm_mca_cap; + + smm_mca_cap = rdmsr(SMM_MCA_CAP_MSR); + if (smm_mca_cap.hi & SMM_CPU_SVRSTR_MASK) { + msr_t smm_feature_control; + + smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR); + smm_feature_control.hi = 0; + smm_feature_control.lo |= SMM_CPU_SAVE_EN; + wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control); + relo_params->smm_save_state_in_msrs = 1; + } + return relo_params->smm_save_state_in_msrs; +} + +/* + * The relocation work is actually performed in SMM context, but the code + * resides in the ramstage module. This occurs by trampolining from the default + * SMRAM entry point to here. + */ +void smm_relocation_handler(int cpu, uintptr_t curr_smbase, + uintptr_t staggered_smbase) +{ + msr_t mtrr_cap; + struct smm_relocation_params *relo_params = &smm_reloc_params; + + printk(BIOS_DEBUG, "In relocation handler: CPU %d\n", cpu); + + /* + * Determine if the processor supports saving state in MSRs. If so, + * enable it before the non-BSPs run so that SMM relocation can occur + * in parallel in the non-BSP CPUs. + */ + if (cpu == 0) { + /* + * If smm_save_state_in_msrs is 1 then that means this is the + * 2nd time through the relocation handler for the BSP. + * Parallel SMM handler relocation is taking place. However, + * it is desired to access other CPUs save state in the real + * SMM handler. Therefore, disable the SMM save state in MSRs + * feature. + */ + if (relo_params->smm_save_state_in_msrs) { + msr_t smm_feature_control; + + smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR); + smm_feature_control.lo &= ~SMM_CPU_SAVE_EN; + wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control); + } else if (bsp_setup_msr_save_state(relo_params)) + /* + * Just return from relocation handler if MSR save + * state is enabled. In that case the BSP will come + * back into the relocation handler to setup the new + * SMBASE as well disabling SMM save state in MSRs. + */ + return; + } + + /* Make appropriate changes to the save state map. */ + update_save_state(cpu, curr_smbase, staggered_smbase, relo_params); + + /* Write SMRR MSRs based on indicated support. */ + mtrr_cap = rdmsr(MTRR_CAP_MSR); + if (mtrr_cap.lo & SMRR_SUPPORTED) + write_smrr(relo_params); +} + +static void fill_in_relocation_params(struct smm_relocation_params *params) +{ + uintptr_t tseg_base; + size_t tseg_size; + /* All range registers are aligned to 4KiB */ + const u32 rmask = ~(4 * KiB - 1); + + smm_region(&tseg_base, &tseg_size); + + if (!IS_ALIGNED(tseg_base, tseg_size)) { + printk(BIOS_WARNING, + "TSEG base not aligned with TSEG SIZE! Not setting SMRR\n"); + return; + } + + smm_subregion(SMM_SUBREGION_CHIPSET, ¶ms->ied_base, ¶ms->ied_size); + + /* SMRR has 32-bits of valid address aligned to 4KiB. */ + params->smrr_base.lo = (tseg_base & rmask) | MTRR_TYPE_WRBACK; + params->smrr_base.hi = 0; + params->smrr_mask.lo = (~(tseg_size - 1) & rmask) | MTRR_PHYS_MASK_VALID; + params->smrr_mask.hi = 0; +} + +static void setup_ied_area(struct smm_relocation_params *params) +{ + char *ied_base; + + struct ied_header ied = { + .signature = "INTEL RSVD", + .size = params->ied_size, + .reserved = {0}, + }; + + ied_base = (void *)params->ied_base; + + printk(BIOS_DEBUG, "IED base = 0x%08x\n", (u32)params->ied_base); + printk(BIOS_DEBUG, "IED size = 0x%08x\n", (u32)params->ied_size); + + /* Place IED header at IEDBASE. */ + memcpy(ied_base, &ied, sizeof(ied)); + + /* Zero out 32KiB at IEDBASE + 1MiB */ + memset(ied_base + 1 * MiB, 0, 32 * KiB); +} + +void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, + size_t *smm_save_state_size) +{ + printk(BIOS_DEBUG, "Setting up SMI for CPU\n"); + + fill_in_relocation_params(&smm_reloc_params); + + smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize); + + if (smm_reloc_params.ied_size) + setup_ied_area(&smm_reloc_params); + + *smm_save_state_size = sizeof(em64t101_smm_state_save_area_t); +} + +void smm_initialize(void) +{ + /* Clear the SMM state in the southbridge. */ + smm_southbridge_clear_state(); + + /* + * Run the relocation handler for on the BSP to check and set up + * parallel SMM relocation. + */ + smm_initiate_relocation(); + + if (smm_reloc_params.smm_save_state_in_msrs) + printk(BIOS_DEBUG, "Doing parallel SMM relocation.\n"); +} + +void smm_relocate(void) +{ + /* + * If smm_save_state_in_msrs is non-zero then parallel SMM relocation + * shall take place. Run the relocation handler a second time on the + * BSP to do * the final move. For APs, a relocation handler always + * needs to be run. + */ + if (smm_reloc_params.smm_save_state_in_msrs) + smm_initiate_relocation_parallel(); + else if (!boot_cpu()) + smm_initiate_relocation(); +} diff --git a/src/soc/intel/elkhartlake/spi.c b/src/soc/intel/elkhartlake/spi.c new file mode 100644 index 0000000000..8fd3126dee --- /dev/null +++ b/src/soc/intel/elkhartlake/spi.c @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <intelblocks/spi.h> +#include <soc/pci_devs.h> + +int spi_soc_devfn_to_bus(unsigned int devfn) +{ + switch (devfn) { + case PCH_DEVFN_SPI: + return 0; + case PCH_DEVFN_GSPI0: + return 1; + case PCH_DEVFN_GSPI1: + return 2; + case PCH_DEVFN_GSPI2: + return 3; + } + return -1; +} diff --git a/src/soc/intel/elkhartlake/systemagent.c b/src/soc/intel/elkhartlake/systemagent.c new file mode 100644 index 0000000000..73f7963b3f --- /dev/null +++ b/src/soc/intel/elkhartlake/systemagent.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <delay.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.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_MMCONF_BASE_ADDRESS, CONFIG_SA_PCIEX_LENGTH, + "PCIEXBAR" }, + { MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" }, + { 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; + config_t *config; + + /* Enable Power Aware Interrupt Routing */ + enable_power_aware_intr(); + + /* Enable BIOS Reset CPL */ + enable_bios_reset_cpl(); + + mdelay(1); + config = config_of_soc(); + soc_config = &config->power_limits_config; + set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config); +} diff --git a/src/soc/intel/elkhartlake/uart.c b/src/soc/intel/elkhartlake/uart.c new file mode 100644 index 0000000000..cc0e3a848b --- /dev/null +++ b/src/soc/intel/elkhartlake/uart.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <device/pci_def.h> +#include <intelblocks/gpio.h> +#include <intelblocks/lpss.h> +#include <intelblocks/pcr.h> +#include <intelblocks/uart.h> +#include <soc/iomap.h> +#include <soc/pch.h> +#include <soc/pci_devs.h> +#include <soc/pcr_ids.h> + +const struct uart_gpio_pad_config uart_gpio_pads[] = { + { + .console_index = 0, + .gpios = { + PAD_CFG_NF(GPP_C8, NONE, DEEP, NF1), /* UART0 RX */ + PAD_CFG_NF(GPP_C9, NONE, DEEP, NF1), /* UART0 TX */ + }, + }, + { + .console_index = 1, + .gpios = { + PAD_CFG_NF(GPP_C12, NONE, DEEP, NF1), /* UART1 RX */ + PAD_CFG_NF(GPP_C13, NONE, DEEP, NF1), /* UART1 TX */ + }, + }, + { + .console_index = 2, + .gpios = { + PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), /* UART2 RX */ + PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), /* UART2 TX */ + }, + } +}; + +const int uart_max_index = ARRAY_SIZE(uart_gpio_pads); + +DEVTREE_CONST struct device *soc_uart_console_to_device(int uart_console) +{ + /* + * if index is valid, this function will return corresponding structure + * for uart console else will return NULL. + */ + switch (uart_console) { + case 0: + return pcidev_path_on_root(PCH_DEVFN_UART0); + case 1: + return pcidev_path_on_root(PCH_DEVFN_UART1); + case 2: + return pcidev_path_on_root(PCH_DEVFN_UART2); + default: + printk(BIOS_ERR, "Invalid UART console index\n"); + return NULL; + } +} |