- Various x86 common codes updated for TPL/SPL
- I2C designware driver updated for PCI
- ICH SPI driver updated to support Apollo Lake
- Add Intel FSP2 base support
- Intel Apollo Lake platform specific drivers support
- Add a new board Google Chromebook Coral
This commit is contained in:
Tom Rini 2019-12-18 07:20:19 -05:00
commit c0912f9bbf
223 changed files with 12379 additions and 715 deletions

View File

@ -545,9 +545,14 @@ config SYS_EXTRA_OPTIONS
configuration to Kconfig. Since this option will be removed sometime,
new boards should not use this option.
config SYS_TEXT_BASE
config HAVE_SYS_TEXT_BASE
bool
depends on !NIOS2 && !XTENSA
depends on !EFI_APP
default y
config SYS_TEXT_BASE
depends on HAVE_SYS_TEXT_BASE
default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S
default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I
@ -556,8 +561,6 @@ config SYS_TEXT_BASE
help
The address in memory that U-Boot will be running from, initially.
config SYS_CLK_FREQ
depends on ARC || ARCH_SUNXI || MPC83xx
int "CPU clock frequency"

View File

@ -133,6 +133,9 @@ config SANDBOX
imply PHYLIB
imply DM_MDIO
imply DM_MDIO_MUX
imply ACPI_PMC
imply ACPI_PMC_SANDBOX
imply CMD_PMC
config SH
bool "SuperH architecture"
@ -183,12 +186,14 @@ config X86
imply USB_HOST_ETHER
imply PCH
imply RTC_MC146818
imply IRQ
# Thing to enable for when SPL/TPL are enabled: SPL
imply SPL_DM
imply SPL_OF_LIBFDT
imply SPL_DRIVERS_MISC_SUPPORT
imply SPL_GPIO_SUPPORT
imply SPL_PINCTRL
imply SPL_LIBCOMMON_SUPPORT
imply SPL_LIBGENERIC_SUPPORT
imply SPL_SERIAL_SUPPORT
@ -200,14 +205,12 @@ config X86
imply SPL_SYSCON
# TPL
imply TPL_DM
imply TPL_OF_LIBFDT
imply TPL_DRIVERS_MISC_SUPPORT
imply TPL_GPIO_SUPPORT
imply TPL_PINCTRL
imply TPL_LIBCOMMON_SUPPORT
imply TPL_LIBGENERIC_SUPPORT
imply TPL_SERIAL_SUPPORT
imply TPL_SPI_FLASH_SUPPORT
imply TPL_SPI_SUPPORT
imply TPL_OF_CONTROL
imply TPL_TIMER
imply TPL_REGMAP

View File

@ -22,7 +22,7 @@
#include <asm/arch/cpu.h>
#ifdef CONFIG_DM_GPIO
#if CONFIG_IS_ENABLED(DM_GPIO)
/* Information about a GPIO bank */
struct omap_gpio_platdata {

View File

@ -133,7 +133,7 @@
/*
* Other misc defines
*/
#ifndef CONFIG_DM_GPIO
#if !CONFIG_IS_ENABLED(DM_GPIO)
#define ATMEL_PIO_PORTS 3 /* these SoCs have 3 PIO */
#define ATMEL_BASE_PIO ATMEL_BASE_PIOA
#endif

View File

@ -18,7 +18,7 @@
#define davinci_gpio_bank67 ((struct davinci_gpio *)DAVINCI_GPIO_BANK67)
#define davinci_gpio_bank8 ((struct davinci_gpio *)DAVINCI_GPIO_BANK8)
#ifndef CONFIG_DM_GPIO
#if !CONFIG_IS_ENABLED(DM_GPIO)
#define gpio_status() gpio_info()
#endif
#define GPIO_NAME_SIZE 20

View File

@ -116,7 +116,7 @@ U_BOOT_DEVICES(am33xx_i2c) = {
};
#endif
#ifdef CONFIG_DM_GPIO
#if CONFIG_IS_ENABLED(DM_GPIO)
static const struct omap_gpio_platdata am33xx_gpio[] = {
{ 0, AM33XX_GPIO0_BASE },
{ 1, AM33XX_GPIO1_BASE },
@ -141,7 +141,7 @@ U_BOOT_DEVICES(am33xx_gpios) = {
#endif
#endif
#ifndef CONFIG_DM_GPIO
#if !CONFIG_IS_ENABLED(DM_GPIO)
static const struct gpio_bank gpio_bank_am33xx[] = {
{ (void *)AM33XX_GPIO0_BASE },
{ (void *)AM33XX_GPIO1_BASE },

View File

@ -33,7 +33,7 @@ extern omap3_sysinfo sysinfo;
static void omap3_invalidate_l2_cache_secure(void);
#endif
#ifdef CONFIG_DM_GPIO
#if CONFIG_IS_ENABLED(DM_GPIO)
#if !CONFIG_IS_ENABLED(OF_CONTROL)
/* Manually initialize GPIO banks when OF_CONTROL doesn't */
static const struct omap_gpio_platdata omap34xx_gpio[] = {

View File

@ -25,7 +25,7 @@
u32 *const omap_si_rev = (u32 *)OMAP_SRAM_SCRATCH_OMAP_REV;
#ifndef CONFIG_DM_GPIO
#if !CONFIG_IS_ENABLED(DM_GPIO)
static struct gpio_bank gpio_bank_54xx[8] = {
{ (void *)OMAP54XX_GPIO1_BASE },
{ (void *)OMAP54XX_GPIO2_BASE },

View File

@ -356,6 +356,7 @@ void state_reset_for_test(struct sandbox_state *state)
/* No reset yet, so mark it as such. Always allow power reset */
state->last_sysreset = SYSRESET_COUNT;
state->sysreset_allowed[SYSRESET_POWER_OFF] = true;
state->allow_memio = false;
memset(&state->wdt, '\0', sizeof(state->wdt));
memset(state->spi, '\0', sizeof(state->spi));

View File

@ -100,6 +100,17 @@
};
pci-controller {
pci@1e,0 {
compatible = "sandbox,pmc";
reg = <0xf000 0 0 0 0>;
sandbox,emul = <&pmc_emul>;
gpe0-dwx-mask = <0xf>;
gpe0-dwx-shift-base = <4>;
gpe0-dw = <6 7 9>;
gpe0-sts = <0x20>;
gpe0-en = <0x30>;
};
pci@1f,0 {
compatible = "pci-generic";
reg = <0xf800 0 0 0 0>;
@ -109,6 +120,9 @@
emul {
compatible = "sandbox,pci-emul-parent";
pmc_emul: emul@1e,0 {
compatible = "sandbox,pmc-emul";
};
swap_case_emul: emul@1f,0 {
compatible = "sandbox,swap-case";
};

View File

@ -353,6 +353,10 @@
vss-microvolts = <0>;
};
irq {
compatible = "sandbox,irq";
};
lcd {
u-boot,dm-pre-reloc;
compatible = "sandbox,lcd-sdl";
@ -471,6 +475,27 @@
0x01000810 0 0 0 0>;
sandbox,emul = <&swap_case_emul0_1>;
};
p2sb-pci@2,0 {
compatible = "sandbox,p2sb";
reg = <0x02001010 0 0 0 0>;
sandbox,emul = <&p2sb_emul>;
adder {
intel,p2sb-port-id = <3>;
compatible = "sandbox,adder";
};
};
pci@1e,0 {
compatible = "sandbox,pmc";
reg = <0xf000 0 0 0 0>;
sandbox,emul = <&pmc_emul1e>;
acpi-base = <0x400>;
gpe0-dwx-mask = <0xf>;
gpe0-dwx-shift-base = <4>;
gpe0-dw = <6 7 9>;
gpe0-sts = <0x20>;
gpe0-en = <0x30>;
};
pci@1f,0 {
compatible = "pci-generic";
/* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */
@ -491,6 +516,12 @@
swap_case_emul0_1f: emul0@1f,0 {
compatible = "sandbox,swap-case";
};
p2sb_emul: emul@2,0 {
compatible = "sandbox,p2sb-emul";
};
pmc_emul1e: emul@1e,0 {
compatible = "sandbox,pmc-emul";
};
};
pci1: pci-controller1 {

View File

@ -13,6 +13,8 @@
#define SANDBOX_PCI_VENDOR_ID 0x1234
#define SANDBOX_PCI_SWAP_CASE_EMUL_ID 0x5678
#define SANDBOX_PCI_PMC_EMUL_ID 0x5677
#define SANDBOX_PCI_P2SB_EMUL_ID 0x5676
#define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM
#define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL

View File

@ -106,6 +106,7 @@ source "board/google/Kconfig"
source "board/intel/Kconfig"
# platform-specific options below
source "arch/x86/cpu/apollolake/Kconfig"
source "arch/x86/cpu/baytrail/Kconfig"
source "arch/x86/cpu/braswell/Kconfig"
source "arch/x86/cpu/broadwell/Kconfig"
@ -217,6 +218,14 @@ config SYS_X86_START16
depends on X86_RESET_VECTOR
default 0xfffff800
config HAVE_X86_FIT
bool
help
Enable inclusion of an Intel Firmware Interface Table (FIT) into the
image. This table is supposed to point to microcode and the like. So
far it is just a fixed table with the minimum set of headers, so that
it is actually present.
config X86_LOAD_FROM_32_BIT
bool "Boot from a 32-bit program"
help
@ -326,7 +335,7 @@ config X86_RAMTEST
config FLASH_DESCRIPTOR_FILE
string "Flash descriptor binary filename"
depends on HAVE_INTEL_ME
depends on HAVE_INTEL_ME || FSP_VERSION2
default "descriptor.bin"
help
The filename of the file to use as flash descriptor in the
@ -411,6 +420,54 @@ config FSP_ADDR
The default base address of 0xfffc0000 indicates that the binary must
be located at offset 0xc0000 from the beginning of a 1MB flash device.
if FSP_VERSION2
config FSP_FILE_T
string "Firmware Support Package binary filename (Temp RAM)"
default "fsp_t.bin"
help
The filename of the file to use for the temporary-RAM init phase from
the Firmware Support Package binary. Put this in the board directory.
It is used to set up an initial area of RAM which can be used for the
stack and other purposes, while bringing up the main system DRAM.
config FSP_ADDR_T
hex "Firmware Support Package binary location (Temp RAM)"
default 0xffff8000
help
FSP is not Position-Independent Code (PIC) and FSP components have to
be rebased if placed at a location which is different from the
perferred base address specified during the FSP build. Use Intel's
Binary Configuration Tool (BCT) to do the rebase.
config FSP_FILE_M
string "Firmware Support Package binary filename (Memory Init)"
default "fsp_m.bin"
help
The filename of the file to use for the RAM init phase from the
Firmware Support Package binary. Put this in the board directory.
It is used to set up the main system DRAM and runs in SPL, once
temporary RAM (CAR) is working.
config FSP_FILE_S
string "Firmware Support Package binary filename (Silicon Init)"
default "fsp_s.bin"
help
The filename of the file to use for the Silicon init phase from the
Firmware Support Package binary. Put this in the board directory.
It is used to set up the silicon to work correctly and must be
executed after DRAM is running.
config IFWI_INPUT_FILE
string "Filename containing FIT (Firmware Interface Table) with IFWI"
default "fitimage.bin"
help
The IFWI is obtained by running a tool on this file to extract the
IFWI. Put this in the board directory. The IFWI contains U-Boot TPL,
microcode and other internal items.
endif
config FSP_TEMP_RAM_ADDR
hex
depends on FSP_VERSION1
@ -532,6 +589,10 @@ config HAVE_REFCODE
broadwell) U-Boot will be missing some critical setup steps.
Various peripherals may fail to work.
config HAVE_MICROCODE
bool
default y if !FSP_VERSION2
config SMP
bool "Enable Symmetric Multiprocessing"
default n
@ -595,7 +656,7 @@ config VGA_BIOS_ADDR
config HAVE_VBT
bool "Add a Video BIOS Table (VBT) image"
depends on FSP_VERSION1
depends on HAVE_FSP
help
Select this option if you have a Video BIOS Table (VBT) image that
you would like to add to your ROM. This is normally required if you
@ -823,4 +884,30 @@ config HIGH_TABLE_SIZE
Increse it if the default size does not fit the board's needs.
This is most likely due to a large ACPI DSDT table is used.
config INTEL_CAR_CQOS
bool "Support Intel Cache Quality of Service"
help
Cache Quality of Service allows more fine-grained control of cache
usage. As result, it is possible to set up a portion of L2 cache for
CAR and use the remainder for actual caching.
#
# Each bit in QOS mask controls this many bytes. This is calculated as:
# (CACHE_WAYS / CACHE_BITS_PER_MASK) * CACHE_LINE_SIZE * CACHE_SETS
#
config CACHE_QOS_SIZE_PER_BIT
hex
depends on INTEL_CAR_CQOS
default 0x20000 # 128 KB
config X86_OFFSET_U_BOOT
hex "Offset of U-Boot in ROM image"
depends on HAVE_SYS_TEXT_BASE
default SYS_TEXT_BASE
config X86_OFFSET_SPL
hex "Offset of SPL in ROM image"
depends on SPL && X86
default SPL_TEXT_BASE
endmenu

View File

@ -41,6 +41,7 @@ extra-y += call32.o
endif
obj-y += intel_common/
obj-$(CONFIG_INTEL_APOLLOLAKE) += apollolake/
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_INTEL_BRASWELL) += braswell/
obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
@ -53,7 +54,8 @@ obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-$(CONFIG_INTEL_TANGIER) += tangier/
obj-$(CONFIG_APIC) += lapic.o ioapic.o
obj-y += irq.o
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += irq.o
obj-$(CONFIG_QFW) += qfw_cpu.o
ifndef CONFIG_$(SPL_)X86_64
obj-$(CONFIG_SMP) += mp_init.o
endif

View File

@ -0,0 +1,96 @@
# SPDX-License-Identifier: GPL-2.0
#
# Copyright 2019 Google LLC
#
config INTEL_APOLLOLAKE
bool
select FSP_VERSION2
select HAVE_FSP
select ARCH_MISC_INIT
select USE_CAR
select INTEL_PMC
select TPL_X86_TSC_TIMER_NATIVE
select SPL_PCH_SUPPORT
select TPL_PCH_SUPPORT
select PCH_SUPPORT
select P2SB
imply ENABLE_MRC_CACHE
imply AHCI_PCI
imply SCSI
imply SCSI_AHCI
imply SPI_FLASH
imply USB
imply USB_EHCI_HCD
imply TPL
imply SPL
imply TPL_X86_16BIT_INIT
imply TPL_OF_PLATDATA
imply ACPI_PMC
imply MMC
imply DM_MMC
imply MMC_PCI
imply MMC_SDHCI
imply CMD_MMC
imply VIDEO_FSP
imply PINCTRL_INTEL
imply PINCTRL_INTEL_APL
imply HAVE_VBT
imply HAVE_X86_FIT
imply INTEL_GPIO
imply SMP
if INTEL_APOLLOLAKE
config DCACHE_RAM_BASE
default 0xfef00000
config DCACHE_RAM_SIZE
default 0xc0000
config DCACHE_RAM_MRC_VAR_SIZE
default 0xb0000
config CPU_SPECIFIC_OPTIONS
def_bool y
select SMM_TSEG
select X86_RAMTEST
config SMM_TSEG_SIZE
hex
default 0x800000
config MMCONF_BASE_ADDRESS
hex
default 0xe0000000
config TPL_SIZE_LIMIT
default 0x7800
config CPU_ADDR_BITS
default 39
config APL_SPI_FLASH_BOOT
bool "Support booting with SPI-flash driver instead memory-mapped SPI"
select TPL_SPI_FLASH_SUPPORT
select TPL_SPI_SUPPORT
help
This enables SPI and SPI flash in TPL. Without the this only
available boot method is to use memory-mapped SPI. Since this is
actually fast and produces a TPL which is 7KB smaller, memory-mapped
SPI is the default.
config APL_BOOT_FROM_FAST_SPI_FLASH
bool "Boot using SPI flash driver"
select APL_SPI_FLASH_BOOT
help
This option is separate from APL_SPI_FLASH_BOOT since it is useful to
be able to compare booting speed with the same build. Enable this to
use the SPI-flash driver to load SPL, U-Boot and FSP-M. For technical
reasons FSP-S is currently always loaded from memory-mapped SPI. See
Apollo Lake's arch_fsp_init_r() for details about that.
config VBT_ADDR
default 0xff3f1000
endif

View File

@ -0,0 +1,27 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2019 Google LLC
obj-$(CONFIG_SPL_BUILD) += cpu_spl.o
obj-$(CONFIG_SPL_BUILD) += spl.o
obj-$(CONFIG_SPL_BUILD) += systemagent.o
obj-y += cpu_common.o
ifndef CONFIG_TPL_BUILD
obj-y += cpu.o
obj-y += punit.o
ifdef CONFIG_SPL_BUILD
obj-y += fsp_m.o
endif
endif
ifndef CONFIG_SPL_BUILD
obj-y += fsp_s.o
endif
obj-y += hostbridge.o
obj-y += itss.o
obj-y += lpc.o
obj-y += p2sb.o
obj-y += pch.o
obj-y += pmc.o
obj-y += uart.o

View File

@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <asm/cpu_common.h>
#include <asm/cpu_x86.h>
static int apl_get_info(struct udevice *dev, struct cpu_info *info)
{
return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
}
static int apl_get_count(struct udevice *dev)
{
return 4;
}
static const struct cpu_ops cpu_x86_apl_ops = {
.get_desc = cpu_x86_get_desc,
.get_info = apl_get_info,
.get_count = apl_get_count,
.get_vendor = cpu_x86_get_vendor,
};
static const struct udevice_id cpu_x86_apl_ids[] = {
{ .compatible = "intel,apl-cpu" },
{ }
};
U_BOOT_DRIVER(cpu_x86_apl_drv) = {
.name = "cpu_x86_apl",
.id = UCLASS_CPU,
.of_match = cpu_x86_apl_ids,
.bind = cpu_x86_bind,
.ops = &cpu_x86_apl_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <asm/cpu_common.h>
#include <asm/msr.h>
void cpu_flush_l1d_to_l2(void)
{
struct msr_t msr;
msr = msr_read(MSR_POWER_MISC);
msr.lo |= FLUSH_DL1_L2;
msr_write(MSR_POWER_MISC, msr);
}

View File

@ -0,0 +1,271 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*
* Portions taken from coreboot
*/
#include <common.h>
#include <acpi_s3.h>
#include <dm.h>
#include <ec_commands.h>
#include <log.h>
#include <spi_flash.h>
#include <spl.h>
#include <syscon.h>
#include <asm/cpu.h>
#include <asm/cpu_common.h>
#include <asm/cpu_x86.h>
#include <asm/fast_spi.h>
#include <asm/intel_pinctrl.h>
#include <asm/intel_regs.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/iomap.h>
#include <asm/arch/lpc.h>
#include <asm/arch/pch.h>
#include <asm/arch/systemagent.h>
#include <asm/arch/uart.h>
#include <asm/fsp2/fsp_api.h>
#include <linux/sizes.h>
#include <power/acpi_pmc.h>
/* Define this here to avoid referencing any drivers for the debug UART 1 */
#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0)
static void pch_uart_init(void)
{
/*
* Set up the pinmux so that the UART rx/tx signals are connected
* outside the SoC.
*
* There are about 500 lines of code required to program the GPIO
* configuration for the UARTs. But it boils down to four writes, and
* for the debug UART we want the minimum possible amount of code before
* the UART is running. So just add the magic writes here. See
* apl_hostbridge_early_init_pinctrl() for the full horror.
*/
if (PCI_FUNC(PCH_DEV_UART) == 1) {
writel(0x40000402, 0xd0c50650);
writel(0x3c47, 0xd0c50654);
writel(0x40000400, 0xd0c50658);
writel(0x3c48, 0xd0c5065c);
} else { /* UART2 */
writel(0x40000402, 0xd0c50670);
writel(0x3c4b, 0xd0c50674);
writel(0x40000400, 0xd0c50678);
writel(0x3c4c, 0xd0c5067c);
}
#ifdef CONFIG_DEBUG_UART
apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
#endif
}
static void p2sb_enable_bar(ulong bar)
{
/* Enable PCR Base address in PCH */
pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
PCI_SIZE_32);
pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
/* Enable P2SB MSE */
pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
PCI_SIZE_8);
}
/*
* board_debug_uart_init() - Init the debug UART ready for use
*
* This is the minimum init needed to get the UART running. It avoids any
* drivers or complex code, so that the UART is running as soon as possible.
*/
void board_debug_uart_init(void)
{
p2sb_enable_bar(IOMAP_P2SB_BAR);
pch_uart_init();
}
static int fast_spi_cache_bios_region(void)
{
uint map_size, offset;
ulong map_base, base;
int ret;
ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE);
if (ret)
return log_msg_ret("early_init", ret);
ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
&offset);
if (ret)
return log_msg_ret("get_mmap", ret);
base = SZ_4G - map_size;
mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
return 0;
}
static void enable_pm_timer_emulation(struct udevice *pmc)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
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_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
debug("PM timer %x %x\n", msr.hi, msr.lo);
msr_write(MSR_EMULATE_PM_TIMER, msr);
}
static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
{
uint base;
uint size;
if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
base = MEC_EMI_BASE;
size = MEC_EMI_SIZE;
} else {
base = EC_HOST_CMD_REGION0;
size = 2 * EC_HOST_CMD_REGION_SIZE;
/* Make sure MEMMAP region follows host cmd region */
assert(base + size == EC_LPC_ADDR_MEMMAP);
size += EC_MEMMAP_SIZE;
}
*out_basep = base;
*out_sizep = size;
}
static void early_ec_init(void)
{
uint base, size;
/*
* Set up LPC decoding for the Chrome OS EC I/O port ranges:
* - Ports 62/66, 60/64, and 200->208
* - Chrome OS EC communication I/O ports
*/
lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 |
LPC_IOE_LGE_200);
google_chromeec_ioport_range(&base, &size);
lpc_open_pmio_window(base, size);
}
static int arch_cpu_init_tpl(void)
{
struct udevice *pmc, *sa, *p2sb, *serial, *spi, *lpc;
int ret;
ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
if (ret)
return log_msg_ret("PMC", ret);
/* Clear global reset promotion bit */
ret = pmc_global_reset_set_enable(pmc, false);
if (ret)
return log_msg_ret("disable global reset", ret);
enable_pm_timer_emulation(pmc);
ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
if (ret)
return log_msg_ret("p2sb", ret);
ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa);
if (ret)
return log_msg_ret("northbridge", ret);
gd->baudrate = CONFIG_BAUDRATE;
ret = uclass_first_device_err(UCLASS_SERIAL, &serial);
if (ret)
return log_msg_ret("serial", ret);
if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
ret = uclass_first_device_err(UCLASS_SPI, &spi);
if (ret)
return log_msg_ret("SPI", ret);
} else {
/* Alternative code if we don't have SPI in TPL */
if (IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH))
printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL");
ret = fast_spi_cache_bios_region();
if (ret)
return log_msg_ret("BIOS cache", ret);
}
ret = pmc_disable_tco(pmc);
if (ret)
return log_msg_ret("disable TCO", ret);
ret = pmc_gpe_init(pmc);
if (ret)
return log_msg_ret("pmc_gpe", ret);
ret = uclass_first_device_err(UCLASS_LPC, &lpc);
if (ret)
return log_msg_ret("lpc", ret);
early_ec_init();
return 0;
}
/*
* Enables several BARs and devices which are needed for memory init
* - MCH_BASE_ADDR is needed in order to talk to the memory controller
* - HPET is enabled because FSP wants to store a pointer to global data in the
* HPET comparator register
*/
static int arch_cpu_init_spl(void)
{
struct udevice *pmc, *p2sb;
int ret;
ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
if (ret)
return log_msg_ret("Could not probe PMC", ret);
ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
if (ret)
return log_msg_ret("Cannot set up p2sb", ret);
lpc_io_setup_comm_a_b();
/* TODO(sjg@chromium.org): Enable upper RTC bank here */
ret = pmc_init(pmc);
if (ret < 0)
return log_msg_ret("Could not init PMC", ret);
#ifdef CONFIG_HAVE_ACPI_RESUME
ret = pmc_prev_sleep_state(pmc);
if (ret < 0)
return log_msg_ret("Could not get PMC sleep state", ret);
gd->arch.prev_sleep_state = ret;
#endif
return 0;
}
int arch_cpu_init(void)
{
int ret = 0;
if (spl_phase() == PHASE_TPL)
ret = arch_cpu_init_tpl();
else if (spl_phase() == PHASE_SPL)
ret = arch_cpu_init_spl();
if (ret)
printf("%s: Error %d\n", __func__, ret);
return ret;
}

View File

@ -0,0 +1,210 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/iomap.h>
#include <asm/arch/fsp/fsp_configs.h>
#include <asm/arch/fsp/fsp_m_upd.h>
#include <asm/fsp2/fsp_internal.h>
#include <dm/uclass-internal.h>
/*
* ODT settings:
* If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A and HIGH for ODT_B,
* choose ODT_A_B_HIGH_HIGH. If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A
* and LOW for ODT_B, choose ODT_A_B_HIGH_LOW.
*
* Note that the enum values correspond to the interpreted UPD fields
* within Ch[3:0]_OdtConfig parameters.
*/
enum {
ODT_A_B_HIGH_LOW = 0 << 1,
ODT_A_B_HIGH_HIGH = 1 << 1,
N_WR_24 = 1 << 5,
};
/*
* LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation.
* There are four physical LPDDR4 channels, each 32-bits wide. There are two
* logical channels using two physical channels together to form a 64-bit
* interface to memory for each logical channel.
*/
enum {
LP4_PHYS_CH0A,
LP4_PHYS_CH0B,
LP4_PHYS_CH1A,
LP4_PHYS_CH1B,
LP4_NUM_PHYS_CHANNELS,
};
/*
* The DQs within a physical channel can be bit-swizzled within each byte.
* Within a channel the bytes can be swapped, but the DQs need to be routed
* with the corresponding DQS (strobe).
*/
enum {
LP4_DQS0,
LP4_DQS1,
LP4_DQS2,
LP4_DQS3,
LP4_NUM_BYTE_LANES,
DQ_BITS_PER_DQS = 8,
};
/* Provide bit swizzling per DQS and byte swapping within a channel */
struct lpddr4_chan_swizzle_cfg {
u8 dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS];
};
struct lpddr4_swizzle_cfg {
struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS];
};
static void setup_sdram(struct fsp_m_config *cfg,
const struct lpddr4_swizzle_cfg *swizzle_cfg)
{
const struct lpddr4_chan_swizzle_cfg *sch;
/* Number of bytes to copy per DQS */
const size_t sz = DQ_BITS_PER_DQS;
int chan;
cfg->memory_down = 1;
cfg->scrambler_support = 1;
cfg->channel_hash_mask = 0x36;
cfg->slice_hash_mask = 9;
cfg->interleaved_mode = 2;
cfg->channels_slices_enable = 0;
cfg->min_ref_rate2x_enable = 0;
cfg->dual_rank_support_enable = 1;
/* LPDDR4 is memory down so no SPD addresses */
cfg->dimm0_spd_address = 0;
cfg->dimm1_spd_address = 0;
for (chan = 0; chan < 4; chan++) {
struct fsp_ram_channel *ch = &cfg->chan[chan];
ch->rank_enable = 1;
ch->device_width = 1;
ch->dram_density = 2;
ch->option = 3;
ch->odt_config = ODT_A_B_HIGH_HIGH;
}
/*
* CH0_DQB byte lanes in the bit swizzle configuration field are
* not 1:1. The mapping within the swizzling field is:
* indices [0:7] - byte lane 1 (DQS1) DQ[8:15]
* indices [8:15] - byte lane 0 (DQS0) DQ[0:7]
* indices [16:23] - byte lane 3 (DQS3) DQ[24:31]
* indices [24:31] - byte lane 2 (DQS2) DQ[16:23]
*/
sch = &swizzle_cfg->phys[LP4_PHYS_CH0B];
memcpy(&cfg->ch_bit_swizzling[0][0], &sch->dqs[LP4_DQS1], sz);
memcpy(&cfg->ch_bit_swizzling[0][8], &sch->dqs[LP4_DQS0], sz);
memcpy(&cfg->ch_bit_swizzling[0][16], &sch->dqs[LP4_DQS3], sz);
memcpy(&cfg->ch_bit_swizzling[0][24], &sch->dqs[LP4_DQS2], sz);
/*
* CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
*/
sch = &swizzle_cfg->phys[LP4_PHYS_CH0A];
memcpy(&cfg->ch_bit_swizzling[1][0], &sch->dqs[LP4_DQS0], sz);
memcpy(&cfg->ch_bit_swizzling[1][8], &sch->dqs[LP4_DQS1], sz);
memcpy(&cfg->ch_bit_swizzling[1][16], &sch->dqs[LP4_DQS2], sz);
memcpy(&cfg->ch_bit_swizzling[1][24], &sch->dqs[LP4_DQS3], sz);
sch = &swizzle_cfg->phys[LP4_PHYS_CH1B];
memcpy(&cfg->ch_bit_swizzling[2][0], &sch->dqs[LP4_DQS1], sz);
memcpy(&cfg->ch_bit_swizzling[2][8], &sch->dqs[LP4_DQS0], sz);
memcpy(&cfg->ch_bit_swizzling[2][16], &sch->dqs[LP4_DQS3], sz);
memcpy(&cfg->ch_bit_swizzling[2][24], &sch->dqs[LP4_DQS2], sz);
/*
* CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
*/
sch = &swizzle_cfg->phys[LP4_PHYS_CH1A];
memcpy(&cfg->ch_bit_swizzling[3][0], &sch->dqs[LP4_DQS0], sz);
memcpy(&cfg->ch_bit_swizzling[3][8], &sch->dqs[LP4_DQS1], sz);
memcpy(&cfg->ch_bit_swizzling[3][16], &sch->dqs[LP4_DQS2], sz);
memcpy(&cfg->ch_bit_swizzling[3][24], &sch->dqs[LP4_DQS3], sz);
}
int fspm_update_config(struct udevice *dev, struct fspm_upd *upd)
{
struct fsp_m_config *cfg = &upd->config;
struct fspm_arch_upd *arch = &upd->arch;
arch->nvs_buffer_ptr = NULL;
prepare_mrc_cache(upd);
arch->stack_base = (void *)0xfef96000;
arch->boot_loader_tolum_size = 0;
arch->boot_mode = FSP_BOOT_WITH_FULL_CONFIGURATION;
cfg->serial_debug_port_type = 2;
cfg->serial_debug_port_device = 2;
cfg->serial_debug_port_stride_size = 2;
cfg->serial_debug_port_address = 0;
cfg->package = 1;
/* Don't enforce a memory size limit */
cfg->memory_size_limit = 0;
cfg->low_memory_max_value = 2048; /* 2 GB */
/* No restrictions on memory above 4GiB */
cfg->high_memory_max_value = 0;
/* Always default to attempt to use saved training data */
cfg->disable_fast_boot = 0;
const u8 *swizzle_data;
swizzle_data = dev_read_u8_array_ptr(dev, "lpddr4-swizzle",
LP4_NUM_BYTE_LANES *
DQ_BITS_PER_DQS *
LP4_NUM_PHYS_CHANNELS);
if (!swizzle_data)
return log_msg_ret("Cannot read swizzel data", -EINVAL);
setup_sdram(cfg, (struct lpddr4_swizzle_cfg *)swizzle_data);
cfg->pre_mem_gpio_table_ptr = 0;
cfg->profile = 0xb;
cfg->msg_level_mask = 0;
/* other */
cfg->skip_cse_rbp = 1;
cfg->periodic_retraining_disable = 0;
cfg->enable_s3_heci2 = 0;
return 0;
}
/*
* The FSP-M binary appears to break the SPI controller. It can be fixed by
* writing the BAR again, so do that here
*/
int fspm_done(struct udevice *dev)
{
struct udevice *spi;
int ret;
/* Don't probe the device, since that reads the BAR */
ret = uclass_find_first_device(UCLASS_SPI, &spi);
if (ret)
return log_msg_ret("SPI", ret);
if (!spi)
return log_msg_ret("no SPI", -ENODEV);
dm_pci_write_config32(spi, PCI_BASE_ADDRESS_0,
IOMAP_SPI_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
return 0;
}

View File

@ -0,0 +1,661 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <acpi_s3.h>
#include <binman.h>
#include <dm.h>
#include <irq.h>
#include <asm/intel_pinctrl.h>
#include <asm/io.h>
#include <asm/intel_regs.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
#include <asm/pci.h>
#include <asm/arch/cpu.h>
#include <asm/arch/systemagent.h>
#include <asm/arch/fsp/fsp_configs.h>
#include <asm/arch/fsp/fsp_s_upd.h>
#define PCH_P2SB_E0 0xe0
#define HIDE_BIT BIT(0)
#define INTEL_GSPI_MAX 3
#define INTEL_I2C_DEV_MAX 8
#define MAX_USB2_PORTS 8
enum {
CHIPSET_LOCKDOWN_FSP = 0, /* FSP handles locking per UPDs */
CHIPSET_LOCKDOWN_COREBOOT, /* coreboot handles locking */
};
enum i2c_speed {
I2C_SPEED_STANDARD = 100000,
I2C_SPEED_FAST = 400000,
I2C_SPEED_FAST_PLUS = 1000000,
I2C_SPEED_HIGH = 3400000,
I2C_SPEED_FAST_ULTRA = 5000000,
};
/*
* Timing values are in units of clock period, with the clock speed
* provided by the SOC
*
* TODO(sjg@chromium.org): Connect this up to the I2C driver
*/
struct dw_i2c_speed_config {
enum i2c_speed speed;
/* SCL high and low period count */
u16 scl_lcnt;
u16 scl_hcnt;
/*
* SDA hold time should be 300ns in standard and fast modes
* and long enough for deterministic logic level change in
* fast-plus and high speed modes.
*
* [15:0] SDA TX Hold Time
* [23:16] SDA RX Hold Time
*/
u32 sda_hold;
};
/* Serial IRQ control. SERIRQ_QUIET is the default (0) */
enum serirq_mode {
SERIRQ_QUIET,
SERIRQ_CONTINUOUS,
SERIRQ_OFF,
};
/*
* This I2C controller has support for 3 independent speed configs but can
* support both FAST_PLUS and HIGH speeds through the same set of speed
* config registers. These are treated separately so the speed config values
* can be provided via ACPI to the OS.
*/
#define DW_I2C_SPEED_CONFIG_COUNT 4
struct dw_i2c_bus_config {
/* Bus should be enabled in TPL with temporary base */
int early_init;
/* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
enum i2c_speed speed;
/*
* If rise_time_ns is non-zero the calculations for lcnt and hcnt
* registers take into account the times of the bus. However, if
* there is a match in speed_config those register values take
* precedence
*/
int rise_time_ns;
int fall_time_ns;
int data_hold_time_ns;
/* Specific bus speed configuration */
struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT];
};
struct gspi_cfg {
/* Bus speed in MHz */
u32 speed_mhz;
/* Bus should be enabled prior to ramstage with temporary base */
u8 early_init;
};
/*
* This structure will hold data required by common blocks.
* These are soc specific configurations which will be filled by soc.
* We'll fill this structure once during init and use the data in common block.
*/
struct soc_intel_common_config {
int chipset_lockdown;
struct gspi_cfg gspi[INTEL_GSPI_MAX];
struct dw_i2c_bus_config i2c[INTEL_I2C_DEV_MAX];
};
enum pnp_settings {
PNP_PERF,
PNP_POWER,
PNP_PERF_POWER,
};
struct usb2_eye_per_port {
u8 per_port_tx_pe_half;
u8 per_port_pe_txi_set;
u8 per_port_txi_set;
u8 hs_skew_sel;
u8 usb_tx_emphasis_en;
u8 per_port_rxi_set;
u8 hs_npre_drv_sel;
u8 override_en;
};
struct apl_config {
/* Common structure containing soc config data required by common code*/
struct soc_intel_common_config common_soc_config;
/*
* Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has
* four CLKREQ inputs, but six root ports. Root ports without an
* associated CLKREQ signal must be marked with "CLKREQ_DISABLED"
*/
u8 pcie_rp_clkreq_pin[MAX_PCIE_PORTS];
/* Enable/disable hot-plug for root ports (0 = disable, 1 = enable) */
u8 pcie_rp_hotplug_enable[MAX_PCIE_PORTS];
/* De-emphasis enable configuration for each PCIe root port */
u8 pcie_rp_deemphasis_enable[MAX_PCIE_PORTS];
/*
* [14:8] DDR mode Number of dealy elements.Each = 125pSec.
* [6:0] SDR mode Number of dealy elements.Each = 125pSec.
*/
u32 emmc_tx_cmd_cntl;
/*
* [14:8] HS400 mode Number of dealy elements.Each = 125pSec.
* [6:0] SDR104/HS200 mode Number of dealy elements.Each = 125pSec.
*/
u32 emmc_tx_data_cntl1;
/*
* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
* [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
* [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
* [6:0] SDR12/Compatibility mode Number of dealy elements.
* Each = 125pSec.
*/
u32 emmc_tx_data_cntl2;
/*
* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
* [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
* [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
* [6:0] SDR12/Compatibility mode Number of dealy elements.
* Each = 125pSec.
*/
u32 emmc_rx_cmd_data_cntl1;
/*
* [14:8] HS400 mode 1 Number of dealy elements.Each = 125pSec.
* [6:0] HS400 mode 2 Number of dealy elements.Each = 125pSec.
*/
u32 emmc_rx_strobe_cntl;
/*
* [13:8] Auto Tuning mode Number of dealy elements.Each = 125pSec.
* [6:0] SDR104/HS200 Number of dealy elements.Each = 125pSec.
*/
u32 emmc_rx_cmd_data_cntl2;
/* Select the eMMC max speed allowed */
u32 emmc_host_max_speed;
/* Specifies on which IRQ the SCI will internally appear */
u32 sci_irq;
/* Configure serial IRQ (SERIRQ) line */
enum serirq_mode serirq_mode;
/* Configure LPSS S0ix Enable */
bool lpss_s0ix_enable;
/* Enable DPTF support */
bool dptf_enable;
/* TCC activation offset value in degrees Celsius */
int tcc_offset;
/*
* Configure Audio clk gate and power gate
* IOSF-SB port ID 92 offset 0x530 [5] and [3]
*/
bool hdaudio_clk_gate_enable;
bool hdaudio_pwr_gate_enable;
bool hdaudio_bios_config_lockdown;
/* SLP S3 minimum assertion width */
int slp_s3_assertion_width_usecs;
/* GPIO pin for PERST_0 */
u32 prt0_gpio;
/* USB2 eye diagram settings per port */
struct usb2_eye_per_port usb2eye[MAX_USB2_PORTS];
/* GPIO SD card detect pin */
unsigned int sdcard_cd_gpio;
/*
* PRMRR size setting with three options
* 0x02000000 - 32MiB
* 0x04000000 - 64MiB
* 0x08000000 - 128MiB
*/
u32 PrmrrSize;
/*
* Enable SGX feature.
* Enabling SGX feature is 2 step process,
* (1) set sgx_enable = 1
* (2) set PrmrrSize to supported size
*/
bool sgx_enable;
/*
* Select PNP Settings.
* (0) Performance,
* (1) Power
* (2) Power & Performance
*/
enum pnp_settings pnp_settings;
/*
* PMIC PCH_PWROK delay configuration - IPC Configuration
* Upd for changing PCH_PWROK delay configuration : I2C_Slave_Address
* (31:24) + Register_Offset (23:16) + OR Value (15:8) + AND Value (7:0)
*/
u32 pmic_pmc_ipc_ctrl;
/*
* Options to disable XHCI Link Compliance Mode. Default is FALSE to not
* disable Compliance Mode. Set TRUE to disable Compliance Mode.
* 0:FALSE(Default), 1:True.
*/
bool disable_compliance_mode;
/*
* Options to change USB3 ModPhy setting for the Integrated Filter (IF)
* value. Default is 0 to not changing default IF value (0x12). Set
* value with the range from 0x01 to 0xff to change IF value.
*/
u32 mod_phy_if_value;
/*
* Options to bump USB3 LDO voltage. Default is FALSE to not increasing
* LDO voltage. Set TRUE to increase LDO voltage with 40mV.
* 0:FALSE (default), 1:True.
*/
bool mod_phy_voltage_bump;
/*
* Options to adjust PMIC Vdd2 voltage. Default is 0 to not adjusting
* the PMIC Vdd2 default voltage 1.20v. Upd for changing Vdd2 Voltage
* configuration: I2C_Slave_Address (31:23) + Register_Offset (23:16)
* + OR Value (15:8) + AND Value (7:0) through BUCK5_VID[3:2]:
* 00=1.10v, 01=1.15v, 10=1.24v, 11=1.20v (default).
*/
u32 pmic_vdd2_voltage;
/* Option to enable VTD feature */
bool enable_vtd;
};
static int get_config(struct udevice *dev, struct apl_config *apl)
{
const u8 *ptr;
ofnode node;
u32 emmc[4];
int ret;
memset(apl, '\0', sizeof(*apl));
node = dev_read_subnode(dev, "fsp-s");
if (!ofnode_valid(node))
return log_msg_ret("fsp-s settings", -ENOENT);
ptr = ofnode_read_u8_array_ptr(node, "pcie-rp-clkreq-pin",
MAX_PCIE_PORTS);
if (!ptr)
return log_msg_ret("pcie-rp-clkreq-pin", -EINVAL);
memcpy(apl->pcie_rp_clkreq_pin, ptr, MAX_PCIE_PORTS);
ret = ofnode_read_u32(node, "prt0-gpio", &apl->prt0_gpio);
if (ret)
return log_msg_ret("prt0-gpio", ret);
ret = ofnode_read_u32(node, "sdcard-cd-gpio", &apl->sdcard_cd_gpio);
if (ret)
return log_msg_ret("sdcard-cd-gpio", ret);
ret = ofnode_read_u32_array(node, "emmc", emmc, ARRAY_SIZE(emmc));
if (ret)
return log_msg_ret("emmc", ret);
apl->emmc_tx_data_cntl1 = emmc[0];
apl->emmc_tx_data_cntl2 = emmc[1];
apl->emmc_rx_cmd_data_cntl1 = emmc[2];
apl->emmc_rx_cmd_data_cntl2 = emmc[3];
apl->dptf_enable = ofnode_read_bool(node, "dptf-enable");
apl->hdaudio_clk_gate_enable = ofnode_read_bool(node,
"hdaudio-clk-gate-enable");
apl->hdaudio_pwr_gate_enable = ofnode_read_bool(node,
"hdaudio-pwr-gate-enable");
apl->hdaudio_bios_config_lockdown = ofnode_read_bool(node,
"hdaudio-bios-config-lockdown");
apl->lpss_s0ix_enable = ofnode_read_bool(node, "lpss-s0ix-enable");
/* Santa */
apl->usb2eye[1].per_port_pe_txi_set = 7;
apl->usb2eye[1].per_port_txi_set = 2;
return 0;
}
static void apl_fsp_silicon_init_params_cb(struct apl_config *apl,
struct fsp_s_config *cfg)
{
u8 port;
for (port = 0; port < MAX_USB2_PORTS; port++) {
if (apl->usb2eye[port].per_port_tx_pe_half)
cfg->port_usb20_per_port_tx_pe_half[port] =
apl->usb2eye[port].per_port_tx_pe_half;
if (apl->usb2eye[port].per_port_pe_txi_set)
cfg->port_usb20_per_port_pe_txi_set[port] =
apl->usb2eye[port].per_port_pe_txi_set;
if (apl->usb2eye[port].per_port_txi_set)
cfg->port_usb20_per_port_txi_set[port] =
apl->usb2eye[port].per_port_txi_set;
if (apl->usb2eye[port].hs_skew_sel)
cfg->port_usb20_hs_skew_sel[port] =
apl->usb2eye[port].hs_skew_sel;
if (apl->usb2eye[port].usb_tx_emphasis_en)
cfg->port_usb20_i_usb_tx_emphasis_en[port] =
apl->usb2eye[port].usb_tx_emphasis_en;
if (apl->usb2eye[port].per_port_rxi_set)
cfg->port_usb20_per_port_rxi_set[port] =
apl->usb2eye[port].per_port_rxi_set;
if (apl->usb2eye[port].hs_npre_drv_sel)
cfg->port_usb20_hs_npre_drv_sel[port] =
apl->usb2eye[port].hs_npre_drv_sel;
}
}
int fsps_update_config(struct udevice *dev, ulong rom_offset,
struct fsps_upd *upd)
{
struct fsp_s_config *cfg = &upd->config;
struct apl_config *apl;
struct binman_entry vbt;
void *buf;
int ret;
ret = binman_entry_find("intel-vbt", &vbt);
if (ret)
return log_msg_ret("Cannot find VBT", ret);
vbt.image_pos += rom_offset;
buf = malloc(vbt.size);
if (!buf)
return log_msg_ret("Alloc VBT", -ENOMEM);
/*
* Load VBT before devicetree-specific config. This only supports
* memory-mapped SPI at present.
*/
bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
memcpy(buf, (void *)vbt.image_pos, vbt.size);
bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
if (*(u32 *)buf != VBT_SIGNATURE)
return log_msg_ret("VBT signature", -EINVAL);
cfg->graphics_config_ptr = (ulong)buf;
apl = malloc(sizeof(*apl));
if (!apl)
return log_msg_ret("config", -ENOMEM);
get_config(dev, apl);
cfg->ish_enable = 0;
cfg->enable_sata = 0;
cfg->pcie_root_port_en[2] = 0;
cfg->pcie_rp_hot_plug[2] = 0;
cfg->pcie_root_port_en[3] = 0;
cfg->pcie_rp_hot_plug[3] = 0;
cfg->pcie_root_port_en[4] = 0;
cfg->pcie_rp_hot_plug[4] = 0;
cfg->pcie_root_port_en[5] = 0;
cfg->pcie_rp_hot_plug[5] = 0;
cfg->pcie_root_port_en[1] = 0;
cfg->pcie_rp_hot_plug[1] = 0;
cfg->usb_otg = 0;
cfg->i2c6_enable = 0;
cfg->i2c7_enable = 0;
cfg->hsuart3_enable = 0;
cfg->spi1_enable = 0;
cfg->spi2_enable = 0;
cfg->sdio_enabled = 0;
memcpy(cfg->pcie_rp_clk_req_number, apl->pcie_rp_clkreq_pin,
sizeof(cfg->pcie_rp_clk_req_number));
memcpy(cfg->pcie_rp_hot_plug, apl->pcie_rp_hotplug_enable,
sizeof(cfg->pcie_rp_hot_plug));
switch (apl->serirq_mode) {
case SERIRQ_QUIET:
cfg->sirq_enable = 1;
cfg->sirq_mode = 0;
break;
case SERIRQ_CONTINUOUS:
cfg->sirq_enable = 1;
cfg->sirq_mode = 1;
break;
case SERIRQ_OFF:
default:
cfg->sirq_enable = 0;
break;
}
if (apl->emmc_tx_cmd_cntl)
cfg->emmc_tx_cmd_cntl = apl->emmc_tx_cmd_cntl;
if (apl->emmc_tx_data_cntl1)
cfg->emmc_tx_data_cntl1 = apl->emmc_tx_data_cntl1;
if (apl->emmc_tx_data_cntl2)
cfg->emmc_tx_data_cntl2 = apl->emmc_tx_data_cntl2;
if (apl->emmc_rx_cmd_data_cntl1)
cfg->emmc_rx_cmd_data_cntl1 = apl->emmc_rx_cmd_data_cntl1;
if (apl->emmc_rx_strobe_cntl)
cfg->emmc_rx_strobe_cntl = apl->emmc_rx_strobe_cntl;
if (apl->emmc_rx_cmd_data_cntl2)
cfg->emmc_rx_cmd_data_cntl2 = apl->emmc_rx_cmd_data_cntl2;
if (apl->emmc_host_max_speed)
cfg->e_mmc_host_max_speed = apl->emmc_host_max_speed;
cfg->lpss_s0ix_enable = apl->lpss_s0ix_enable;
cfg->skip_mp_init = true;
/* Disable setting of EISS bit in FSP */
cfg->spi_eiss = 0;
/* Disable FSP from locking access to the RTC NVRAM */
cfg->rtc_lock = 0;
/* Enable Audio clk gate and power gate */
cfg->hd_audio_clk_gate = apl->hdaudio_clk_gate_enable;
cfg->hd_audio_pwr_gate = apl->hdaudio_pwr_gate_enable;
/* Bios config lockdown Audio clk and power gate */
cfg->bios_cfg_lock_down = apl->hdaudio_bios_config_lockdown;
apl_fsp_silicon_init_params_cb(apl, cfg);
cfg->usb_otg = true;
cfg->vtd_enable = apl->enable_vtd;
return 0;
}
static void p2sb_set_hide_bit(pci_dev_t dev, int hide)
{
pci_x86_clrset_config(dev, PCH_P2SB_E0 + 1, HIDE_BIT,
hide ? HIDE_BIT : 0, PCI_SIZE_8);
}
/* Configure package power limits */
static int set_power_limits(struct udevice *dev)
{
msr_t rapl_msr_reg, limit;
u32 power_unit;
u32 tdp, min_power, max_power;
u32 pl2_val;
u32 override_tdp[2];
int ret;
/* Get units */
rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT);
power_unit = 1 << (rapl_msr_reg.lo & 0xf);
/* Get power defaults for this SKU */
rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU);
tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK;
pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK;
max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
if (min_power > 0 && tdp < min_power)
tdp = min_power;
if (max_power > 0 && tdp > max_power)
tdp = max_power;
ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp,
ARRAY_SIZE(override_tdp));
if (ret)
return log_msg_ret("tdp-pl-override-mw", ret);
/* Set PL1 override value */
if (override_tdp[0])
tdp = override_tdp[0] * power_unit / 1000;
/* Set PL2 override value */
if (override_tdp[1])
pl2_val = override_tdp[1] * power_unit / 1000;
/* Set long term power limit to TDP */
limit.lo = tdp & PKG_POWER_LIMIT_MASK;
/* Set PL1 Pkg Power clamp bit */
limit.lo |= PKG_POWER_LIMIT_CLAMP;
limit.lo |= PKG_POWER_LIMIT_EN;
limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT &
PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;
/* Set short term power limit PL2 */
limit.hi = pl2_val & PKG_POWER_LIMIT_MASK;
limit.hi |= PKG_POWER_LIMIT_EN;
/* Program package power limits in RAPL MSR */
msr_write(MSR_PKG_POWER_LIMIT, limit);
log_info("RAPL PL1 %d.%dW\n", tdp / power_unit,
100 * (tdp % power_unit) / power_unit);
log_info("RAPL PL2 %d.%dW\n", pl2_val / power_unit,
100 * (pl2_val % power_unit) / power_unit);
/*
* Sett RAPL MMIO register for Power limits. RAPL driver is using MSR
* instead of MMIO, so disable LIMIT_EN bit for MMIO
*/
writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL));
writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4));
return 0;
}
int p2sb_unhide(void)
{
pci_dev_t dev = PCI_BDF(0, 0xd, 0);
ulong val;
p2sb_set_hide_bit(dev, 0);
pci_x86_read_config(dev, PCI_VENDOR_ID, &val, PCI_SIZE_16);
if (val != PCI_VENDOR_ID_INTEL)
return log_msg_ret("p2sb unhide", -EIO);
return 0;
}
/* Overwrites the SCI IRQ if another IRQ number is given by device tree */
static void set_sci_irq(void)
{
/* Skip this for now */
}
int arch_fsps_preinit(void)
{
struct udevice *itss;
int ret;
ret = uclass_first_device_err(UCLASS_IRQ, &itss);
if (ret)
return log_msg_ret("no itss", ret);
/*
* Snapshot the current GPIO IRQ polarities. FSP is setting a default
* policy that doesn't honour boards' requirements
*/
irq_snapshot_polarities(itss);
/*
* Clear the GPI interrupt status and enable registers. These
* registers do not get reset to default state when booting from S5.
*/
ret = pinctrl_gpi_clear_int_cfg();
if (ret)
return log_msg_ret("gpi_clear", ret);
return 0;
}
int arch_fsp_init_r(void)
{
#ifdef CONFIG_HAVE_ACPI_RESUME
bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
#else
bool s3wake = false;
#endif
struct udevice *dev, *itss;
int ret;
/*
* This must be called before any devices are probed. Put any probing
* into arch_fsps_preinit() above.
*
* We don't use CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH here since it will
* force PCI to be probed.
*/
ret = fsp_silicon_init(s3wake, false);
if (ret)
return ret;
ret = uclass_first_device_err(UCLASS_IRQ, &itss);
if (ret)
return log_msg_ret("no itss", ret);
/* Restore GPIO IRQ polarities back to previous settings */
irq_restore_polarities(itss);
/* soc_init() */
ret = p2sb_unhide();
if (ret)
return log_msg_ret("unhide p2sb", ret);
/* Set RAPL MSR for Package power limits*/
ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
if (ret)
return log_msg_ret("Cannot get northbridge", ret);
set_power_limits(dev);
/*
* FSP-S routes SCI to IRQ 9. With the help of this function you can
* select another IRQ for SCI.
*/
set_sci_irq();
return 0;
}

View File

@ -0,0 +1,179 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
#include <spl.h>
#include <asm/intel_pinctrl.h>
#include <asm/intel_regs.h>
#include <asm/pci.h>
#include <asm/arch/systemagent.h>
/**
* struct apl_hostbridge_platdata - platform data for hostbridge
*
* @dtplat: Platform data for of-platdata
* @early_pads: Early pad data to set up, each (pad, cfg0, cfg1)
* @early_pads_count: Number of pads to process
* @pciex_region_size: BAR length in bytes
* @bdf: Bus/device/function of hostbridge
*/
struct apl_hostbridge_platdata {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_intel_apl_hostbridge dtplat;
#endif
u32 *early_pads;
int early_pads_count;
uint pciex_region_size;
pci_dev_t bdf;
};
enum {
PCIEXBAR = 0x60,
PCIEXBAR_LENGTH_256MB = 0,
PCIEXBAR_LENGTH_128MB,
PCIEXBAR_LENGTH_64MB,
PCIEXBAR_PCIEXBAREN = 1 << 0,
TSEG = 0xb8, /* TSEG base */
};
static int apl_hostbridge_early_init_pinctrl(struct udevice *dev)
{
struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
struct udevice *pinctrl;
int ret;
ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl);
if (ret)
return log_msg_ret("no hostbridge pinctrl", ret);
return pinctrl_config_pads(pinctrl, plat->early_pads,
plat->early_pads_count);
}
static int apl_hostbridge_early_init(struct udevice *dev)
{
struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
u32 region_size;
ulong base;
u32 reg;
int ret;
/* Set up the MCHBAR */
pci_x86_read_config(plat->bdf, MCHBAR, &base, PCI_SIZE_32);
base = MCH_BASE_ADDRESS;
pci_x86_write_config(plat->bdf, MCHBAR, base | 1, PCI_SIZE_32);
/*
* The PCIEXBAR is assumed to live in the memory mapped IO space under
* 4GiB
*/
pci_x86_write_config(plat->bdf, PCIEXBAR + 4, 0, PCI_SIZE_32);
switch (plat->pciex_region_size >> 20) {
default:
case 256:
region_size = PCIEXBAR_LENGTH_256MB;
break;
case 128:
region_size = PCIEXBAR_LENGTH_128MB;
break;
case 64:
region_size = PCIEXBAR_LENGTH_64MB;
break;
}
reg = CONFIG_MMCONF_BASE_ADDRESS | (region_size << 1)
| PCIEXBAR_PCIEXBAREN;
pci_x86_write_config(plat->bdf, PCIEXBAR, reg, PCI_SIZE_32);
/*
* TSEG defines the base of SMM range. BIOS determines the base
* of TSEG memory which must be at or below Graphics base of GTT
* Stolen memory, hence its better to clear TSEG register early
* to avoid power on default non-zero value (if any).
*/
pci_x86_write_config(plat->bdf, TSEG, 0, PCI_SIZE_32);
ret = apl_hostbridge_early_init_pinctrl(dev);
if (ret)
return log_msg_ret("pinctrl", ret);
return 0;
}
static int apl_hostbridge_ofdata_to_platdata(struct udevice *dev)
{
struct apl_hostbridge_platdata *plat = dev_get_platdata(dev);
struct udevice *pinctrl;
int ret;
/*
* The host bridge holds the early pad data needed to get through TPL.
* This is a small amount of data, enough to fit in TPL, so we keep it
* separate from the full pad data, stored in the fsp-s subnode. That
* subnode is not present in TPL, to save space.
*/
ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl);
if (ret)
return log_msg_ret("no hostbridge PINCTRL", ret);
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
int root;
/* Get length of PCI Express Region */
plat->pciex_region_size = dev_read_u32_default(dev, "pciex-region-size",
256 << 20);
root = pci_get_devfn(dev);
if (root < 0)
return log_msg_ret("Cannot get host-bridge PCI address", root);
plat->bdf = root;
ret = pinctrl_read_pads(pinctrl, dev_ofnode(dev), "early-pads",
&plat->early_pads, &plat->early_pads_count);
if (ret)
return log_msg_ret("early-pads", ret);
#else
struct dtd_intel_apl_hostbridge *dtplat = &plat->dtplat;
int size;
plat->pciex_region_size = dtplat->pciex_region_size;
plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
/* Assume that if everything is 0, it is empty */
plat->early_pads = dtplat->early_pads;
size = ARRAY_SIZE(dtplat->early_pads);
plat->early_pads_count = pinctrl_count_pads(pinctrl, plat->early_pads,
size);
#endif
return 0;
}
static int apl_hostbridge_probe(struct udevice *dev)
{
if (spl_phase() == PHASE_TPL)
return apl_hostbridge_early_init(dev);
return 0;
}
static const struct udevice_id apl_hostbridge_ids[] = {
{ .compatible = "intel,apl-hostbridge" },
{ }
};
U_BOOT_DRIVER(apl_hostbridge_drv) = {
.name = "intel_apl_hostbridge",
.id = UCLASS_NORTHBRIDGE,
.of_match = apl_hostbridge_ids,
.ofdata_to_platdata = apl_hostbridge_ofdata_to_platdata,
.probe = apl_hostbridge_probe,
.platdata_auto_alloc_size = sizeof(struct apl_hostbridge_platdata),
};

View File

@ -0,0 +1,214 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Something to do with Interrupts, but I don't know what ITSS stands for
*
* Copyright (C) 2017 Intel Corporation.
* Copyright (C) 2017 Siemens AG
* Copyright 2019 Google LLC
*
* Taken from coreboot itss.c
*/
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
#include <irq.h>
#include <p2sb.h>
#include <spl.h>
#include <asm/arch/itss.h>
struct apl_itss_platdata {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
/* Put this first since driver model will copy the data here */
struct dtd_intel_apl_itss dtplat;
#endif
};
/* struct pmc_route - Routing for PMC to GPIO */
struct pmc_route {
u32 pmc;
u32 gpio;
};
struct apl_itss_priv {
struct pmc_route *route;
uint route_count;
u32 irq_snapshot[NUM_IPC_REGS];
};
static int apl_set_polarity(struct udevice *dev, uint irq, bool active_low)
{
u32 mask;
uint reg;
if (irq > ITSS_MAX_IRQ)
return -EINVAL;
reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * (irq / IRQS_PER_IPC);
mask = 1 << (irq % IRQS_PER_IPC);
pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0);
return 0;
}
#ifndef CONFIG_TPL_BUILD
static int apl_snapshot_polarities(struct udevice *dev)
{
struct apl_itss_priv *priv = dev_get_priv(dev);
const int start = GPIO_IRQ_START;
const int end = GPIO_IRQ_END;
int reg_start;
int reg_end;
int i;
reg_start = start / IRQS_PER_IPC;
reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
for (i = reg_start; i < reg_end; i++) {
uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
priv->irq_snapshot[i] = pcr_read32(dev, reg);
}
return 0;
}
static void show_polarities(struct udevice *dev, const char *msg)
{
int i;
log_info("ITSS IRQ Polarities %s:\n", msg);
for (i = 0; i < NUM_IPC_REGS; i++) {
uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
log_info("IPC%d: 0x%08x\n", i, pcr_read32(dev, reg));
}
}
static int apl_restore_polarities(struct udevice *dev)
{
struct apl_itss_priv *priv = dev_get_priv(dev);
const int start = GPIO_IRQ_START;
const int end = GPIO_IRQ_END;
int reg_start;
int reg_end;
int i;
show_polarities(dev, "Before");
reg_start = start / IRQS_PER_IPC;
reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
for (i = reg_start; i < reg_end; i++) {
u32 mask;
u16 reg;
int irq_start;
int irq_end;
irq_start = i * IRQS_PER_IPC;
irq_end = min(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
if (start > irq_end)
continue;
if (end < irq_start)
break;
/* Track bits within the bounds of of the register */
irq_start = max(start, irq_start) % IRQS_PER_IPC;
irq_end = min(end, irq_end) % IRQS_PER_IPC;
/* Create bitmask of the inclusive range of start and end */
mask = (((1U << irq_end) - 1) | (1U << irq_end));
mask &= ~((1U << irq_start) - 1);
reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]);
}
show_polarities(dev, "After");
return 0;
}
#endif
static int apl_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
{
struct apl_itss_priv *priv = dev_get_priv(dev);
struct pmc_route *route;
int i;
for (i = 0, route = priv->route; i < priv->route_count; i++, route++) {
if (pmc_gpe_num == route->pmc)
return route->gpio;
}
return -ENOENT;
}
static int apl_itss_ofdata_to_platdata(struct udevice *dev)
{
struct apl_itss_priv *priv = dev_get_priv(dev);
int ret;
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct apl_itss_platdata *plat = dev_get_platdata(dev);
struct dtd_intel_apl_itss *dtplat = &plat->dtplat;
/*
* It would be nice to do this in the bind() method, but with
* of-platdata binding happens in the order that DM finds things in the
* linker list (i.e. alphabetical order by driver name). So the GPIO
* device may well be bound before its parent (p2sb), and this call
* will fail if p2sb is not bound yet.
*
* TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc
*/
ret = p2sb_set_port_id(dev, dtplat->intel_p2sb_port_id);
if (ret)
return log_msg_ret("Could not set port id", ret);
priv->route = (struct pmc_route *)dtplat->intel_pmc_routes;
priv->route_count = ARRAY_SIZE(dtplat->intel_pmc_routes) /
sizeof(struct pmc_route);
#else
int size;
size = dev_read_size(dev, "intel,pmc-routes");
if (size < 0)
return size;
priv->route = malloc(size);
if (!priv->route)
return -ENOMEM;
ret = dev_read_u32_array(dev, "intel,pmc-routes", (u32 *)priv->route,
size / sizeof(fdt32_t));
if (ret)
return log_msg_ret("Cannot read pmc-routes", ret);
priv->route_count = size / sizeof(struct pmc_route);
#endif
return 0;
}
static const struct irq_ops apl_itss_ops = {
.route_pmc_gpio_gpe = apl_route_pmc_gpio_gpe,
.set_polarity = apl_set_polarity,
#ifndef CONFIG_TPL_BUILD
.snapshot_polarities = apl_snapshot_polarities,
.restore_polarities = apl_restore_polarities,
#endif
};
static const struct udevice_id apl_itss_ids[] = {
{ .compatible = "intel,apl-itss"},
{ }
};
U_BOOT_DRIVER(apl_itss_drv) = {
.name = "intel_apl_itss",
.id = UCLASS_IRQ,
.of_match = apl_itss_ids,
.ops = &apl_itss_ops,
.ofdata_to_platdata = apl_itss_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct apl_itss_platdata),
.priv_auto_alloc_size = sizeof(struct apl_itss_priv),
};

View File

@ -0,0 +1,122 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*
* From coreboot Apollo Lake support lpc.c
*/
#include <common.h>
#include <dm.h>
#include <spl.h>
#include <asm/lpc_common.h>
#include <asm/pci.h>
#include <asm/arch/iomap.h>
#include <asm/arch/lpc.h>
#include <linux/log2.h>
void lpc_enable_fixed_io_ranges(uint io_enables)
{
pci_x86_clrset_config(PCH_DEV_LPC, LPC_IO_ENABLES, 0, io_enables,
PCI_SIZE_16);
}
/*
* Find the first unused IO window.
* Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ...
*/
static int find_unused_pmio_window(void)
{
int i;
ulong lgir;
for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
pci_x86_read_config(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i),
&lgir, PCI_SIZE_32);
if (!(lgir & LPC_LGIR_EN))
return i;
}
return -1;
}
int lpc_open_pmio_window(uint base, uint size)
{
int i, lgir_reg_num;
u32 lgir_reg_offset, lgir, window_size, alignment;
ulong bridged_size, bridge_base;
ulong reg;
log_debug("LPC: Trying to open IO window from %x size %x\n", base,
size);
bridged_size = 0;
bridge_base = base;
while (bridged_size < size) {
/* Each IO range register can only open a 256-byte window */
window_size = min(size, (uint)LPC_LGIR_MAX_WINDOW_SIZE);
/* Window size must be a power of two for the AMASK to work */
alignment = 1UL << (order_base_2(window_size));
window_size = ALIGN(window_size, alignment);
/* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18] */
lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN;
lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK;
/* Skip programming if same range already programmed */
for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
pci_x86_read_config(PCH_DEV_LPC,
LPC_GENERIC_IO_RANGE(i), &reg,
PCI_SIZE_32);
if (lgir == reg)
return -EALREADY;
}
lgir_reg_num = find_unused_pmio_window();
if (lgir_reg_num < 0) {
log_err("LPC: Cannot open IO window: %lx size %lx\n",
bridge_base, size - bridged_size);
log_err("No more IO windows\n");
return -ENOSPC;
}
lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num);
pci_x86_write_config(PCH_DEV_LPC, lgir_reg_offset, lgir,
PCI_SIZE_32);
log_debug("LPC: Opened IO window LGIR%d: base %lx size %x\n",
lgir_reg_num, bridge_base, window_size);
bridged_size += window_size;
bridge_base += window_size;
}
return 0;
}
void lpc_io_setup_comm_a_b(void)
{
/* ComA Range 3F8h-3FFh [2:0] */
u16 com_ranges = LPC_IOD_COMA_RANGE;
u16 com_enable = LPC_IOE_COMA_EN;
/* Setup I/O Decode Range Register for LPC */
pci_write_config16(PCH_DEV_LPC, LPC_IO_DECODE, com_ranges);
/* Enable ComA and ComB Port */
lpc_enable_fixed_io_ranges(com_enable);
}
static const struct udevice_id apl_lpc_ids[] = {
{ .compatible = "intel,apl-lpc" },
{ }
};
/* All pads are LPC already configured by the hostbridge, so no probing here */
U_BOOT_DRIVER(apl_lpc_drv) = {
.name = "intel_apl_lpc",
.id = UCLASS_LPC,
.of_match = apl_lpc_ids,
};

View File

@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Primary-to-Sideband Bridge
*
* Copyright 2019 Google LLC
*/
#define LOG_CATEGORY UCLASS_P2SB
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
#include <p2sb.h>
#include <spl.h>
#include <asm/pci.h>
struct p2sb_platdata {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_intel_apl_p2sb dtplat;
#endif
ulong mmio_base;
pci_dev_t bdf;
};
/* PCI config space registers */
#define HPTC_OFFSET 0x60
#define HPTC_ADDR_ENABLE_BIT BIT(7)
/* High Performance Event Timer Configuration */
#define P2SB_HPTC 0x60
#define P2SB_HPTC_ADDRESS_ENABLE BIT(7)
/*
* ADDRESS_SELECT ENCODING_RANGE
* 0 0xfed0 0000 - 0xfed0 03ff
* 1 0xfed0 1000 - 0xfed0 13ff
* 2 0xfed0 2000 - 0xfed0 23ff
* 3 0xfed0 3000 - 0xfed0 33ff
*/
#define P2SB_HPTC_ADDRESS_SELECT_0 (0 << 0)
#define P2SB_HPTC_ADDRESS_SELECT_1 (1 << 0)
#define P2SB_HPTC_ADDRESS_SELECT_2 (2 << 0)
#define P2SB_HPTC_ADDRESS_SELECT_3 (3 << 0)
/*
* apl_p2sb_early_init() - Enable decoding for HPET range
*
* This is needed by FSP-M which uses the High Precision Event Timer.
*
* @dev: P2SB device
* @return 0 if OK, -ve on error
*/
static int apl_p2sb_early_init(struct udevice *dev)
{
struct p2sb_platdata *plat = dev_get_platdata(dev);
pci_dev_t pdev = plat->bdf;
/*
* Enable decoding for HPET memory address range.
* HPTC_OFFSET(0x60) bit 7, when set the P2SB will decode
* the High Performance Timer memory address range
* selected by bits 1:0
*/
pci_x86_write_config(pdev, HPTC_OFFSET, HPTC_ADDR_ENABLE_BIT,
PCI_SIZE_8);
/* Enable PCR Base address in PCH */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0, plat->mmio_base,
PCI_SIZE_32);
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
/* Enable P2SB MSE */
pci_x86_write_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
return 0;
}
static int apl_p2sb_spl_init(struct udevice *dev)
{
/* Enable decoding for HPET. Needed for FSP global pointer storage */
dm_pci_write_config(dev, P2SB_HPTC, P2SB_HPTC_ADDRESS_SELECT_0 |
P2SB_HPTC_ADDRESS_ENABLE, PCI_SIZE_8);
return 0;
}
int apl_p2sb_ofdata_to_platdata(struct udevice *dev)
{
struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
struct p2sb_platdata *plat = dev_get_platdata(dev);
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
int ret;
if (spl_phase() == PHASE_TPL) {
u32 base[2];
/* TPL sets up the initial BAR */
ret = dev_read_u32_array(dev, "early-regs", base,
ARRAY_SIZE(base));
if (ret)
return log_msg_ret("Missing/short early-regs", ret);
plat->mmio_base = base[0];
plat->bdf = pci_get_devfn(dev);
if (plat->bdf < 0)
return log_msg_ret("Cannot get p2sb PCI address",
plat->bdf);
} else {
plat->mmio_base = dev_read_addr_pci(dev);
/* Don't set BDF since it should not be used */
if (!plat->mmio_base || plat->mmio_base == FDT_ADDR_T_NONE)
return -EINVAL;
}
#else
plat->mmio_base = plat->dtplat.early_regs[0];
plat->bdf = pci_ofplat_get_devfn(plat->dtplat.reg[0]);
#endif
upriv->mmio_base = plat->mmio_base;
debug("p2sb: mmio_base=%x\n", (uint)plat->mmio_base);
return 0;
}
static int apl_p2sb_probe(struct udevice *dev)
{
if (spl_phase() == PHASE_TPL)
return apl_p2sb_early_init(dev);
else if (spl_phase() == PHASE_SPL)
return apl_p2sb_spl_init(dev);
return 0;
}
static int p2sb_child_post_bind(struct udevice *dev)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
int ret;
u32 pid;
ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
if (ret)
return ret;
pplat->pid = pid;
#endif
return 0;
}
static const struct udevice_id apl_p2sb_ids[] = {
{ .compatible = "intel,apl-p2sb" },
{ }
};
U_BOOT_DRIVER(apl_p2sb_drv) = {
.name = "intel_apl_p2sb",
.id = UCLASS_P2SB,
.of_match = apl_p2sb_ids,
.probe = apl_p2sb_probe,
.ofdata_to_platdata = apl_p2sb_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct p2sb_platdata),
.per_child_platdata_auto_alloc_size =
sizeof(struct p2sb_child_platdata),
.child_post_bind = p2sb_child_post_bind,
};

View File

@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <dm.h>
#include <pch.h>
#include <spl.h>
#include <asm/lpc_common.h>
#define BIOS_CTRL 0xdc
static int apl_set_spi_protect(struct udevice *dev, bool protect)
{
if (spl_phase() == PHASE_SPL)
return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
return 0;
}
static const struct pch_ops apl_pch_ops = {
.set_spi_protect = apl_set_spi_protect,
};
static const struct udevice_id apl_pch_ids[] = {
{ .compatible = "intel,apl-pch" },
{ }
};
U_BOOT_DRIVER(apl_pch) = {
.name = "apl_pch",
.id = UCLASS_PCH,
.of_match = apl_pch_ids,
.ops = &apl_pch_ops,
};

View File

@ -0,0 +1,216 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2017 Intel Corporation.
* Copyright 2019 Google LLC
*
* Modified from coreboot pmclib.c, pmc.c and pmutil.c
*/
#define LOG_CATEGORY UCLASS_ACPI_PMC
#include <common.h>
#include <acpi_s3.h>
#include <dt-structs.h>
#include <dm.h>
#include <spl.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <power/acpi_pmc.h>
#define GPIO_GPE_CFG 0x1050
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
#define PRSTS 0x1000
#define GEN_PMCON1 0x1020
#define COLD_BOOT_STS BIT(27)
#define COLD_RESET_STS BIT(26)
#define WARM_RESET_STS BIT(25)
#define GLOBAL_RESET_STS BIT(24)
#define SRS BIT(20)
#define MS4V BIT(18)
#define RPS BIT(2)
#define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \
WARM_RESET_STS | GLOBAL_RESET_STS | \
SRS | MS4V)
#define GEN_PMCON2 0x1024
#define GEN_PMCON3 0x1028
/* Offset of TCO registers from ACPI base I/O address */
#define TCO_REG_OFFSET 0x60
#define TCO1_STS 0x64
#define DMISCI_STS BIT(9)
#define BOOT_STS BIT(18)
#define TCO2_STS 0x66
#define TCO1_CNT 0x68
#define TCO_LOCK BIT(12)
#define TCO2_CNT 0x6a
enum {
ETR = 0x1048,
CF9_LOCK = 1UL << 31,
CF9_GLB_RST = 1 << 20,
};
struct apl_pmc_platdata {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_intel_apl_pmc dtplat;
#endif
pci_dev_t bdf;
};
static int apl_pmc_fill_power_state(struct udevice *dev)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
return 0;
}
static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
/* WAK_STS bit will not be set when waking from G3 state */
if (!(upriv->pm1_sts & WAK_STS) &&
(upriv->gen_pmcon1 & COLD_BOOT_STS))
prev_sleep_state = ACPI_S5;
return prev_sleep_state;
}
static int apl_disable_tco(struct udevice *dev)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
return 0;
}
static int apl_global_reset_set_enable(struct udevice *dev, bool enable)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
if (enable)
setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
else
clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
return 0;
}
int apl_pmc_ofdata_to_uc_platdata(struct udevice *dev)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
struct apl_pmc_platdata *plat = dev_get_platdata(dev);
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
u32 base[6];
int size;
int ret;
ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base));
if (ret)
return log_msg_ret("Missing/short early-regs", ret);
upriv->pmc_bar0 = (void *)base[0];
upriv->pmc_bar2 = (void *)base[2];
upriv->acpi_base = base[4];
/* Since PCI is not enabled, we must get the BDF manually */
plat->bdf = pci_get_devfn(dev);
if (plat->bdf < 0)
return log_msg_ret("Cannot get PMC PCI address", plat->bdf);
/* Get the dwX values for pmc gpe settings */
size = dev_read_size(dev, "gpe0-dw");
if (size < 0)
return log_msg_ret("Cannot read gpe0-dm", size);
upriv->gpe0_count = size / sizeof(u32);
ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw,
upriv->gpe0_count);
if (ret)
return log_msg_ret("Bad gpe0-dw", ret);
return pmc_ofdata_to_uc_platdata(dev);
#else
struct dtd_intel_apl_pmc *dtplat = &plat->dtplat;
plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
upriv->pmc_bar0 = (void *)dtplat->early_regs[0];
upriv->pmc_bar2 = (void *)dtplat->early_regs[2];
upriv->acpi_base = dtplat->early_regs[4];
upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask;
upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base;
upriv->gpe0_sts_reg = dtplat->gpe0_sts;
upriv->gpe0_sts_reg += upriv->acpi_base;
upriv->gpe0_en_reg = dtplat->gpe0_en;
upriv->gpe0_en_reg += upriv->acpi_base;
upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX);
memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw));
#endif
upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
return 0;
}
static int enable_pmcbar(struct udevice *dev)
{
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
struct apl_pmc_platdata *priv = dev_get_platdata(dev);
pci_dev_t pmc = priv->bdf;
/*
* Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit
* BARs.
*/
pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0,
PCI_SIZE_32);
pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2,
PCI_SIZE_32);
pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32);
pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base,
PCI_SIZE_16);
pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO |
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
PCI_SIZE_16);
return 0;
}
static int apl_pmc_probe(struct udevice *dev)
{
if (spl_phase() == PHASE_TPL)
return enable_pmcbar(dev);
return 0;
}
static struct acpi_pmc_ops apl_pmc_ops = {
.init = apl_pmc_fill_power_state,
.prev_sleep_state = apl_prev_sleep_state,
.disable_tco = apl_disable_tco,
.global_reset_set_enable = apl_global_reset_set_enable,
};
static const struct udevice_id apl_pmc_ids[] = {
{ .compatible = "intel,apl-pmc" },
{ }
};
U_BOOT_DRIVER(apl_pmc) = {
.name = "intel_apl_pmc",
.id = UCLASS_ACPI_PMC,
.of_match = apl_pmc_ids,
.ofdata_to_platdata = apl_pmc_ofdata_to_uc_platdata,
.probe = apl_pmc_probe,
.ops = &apl_pmc_ops,
.platdata_auto_alloc_size = sizeof(struct apl_pmc_platdata),
};

View File

@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <dm.h>
#include <spl.h>
#include <asm/cpu.h>
#include <asm/cpu_common.h>
#include <asm/intel_regs.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/arch/systemagent.h>
/*
* Punit Initialisation code. This all isn't documented, but
* this is the recipe.
*/
static int punit_init(struct udevice *dev)
{
struct udevice *cpu;
u32 reg;
ulong start;
int ret;
/* Thermal throttle activation offset */
ret = uclass_first_device_err(UCLASS_CPU, &cpu);
if (ret)
return log_msg_ret("Cannot find CPU", ret);
cpu_configure_thermal_target(cpu);
/*
* Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
* Enable all cores here.
*/
writel(0, MCHBAR_REG(CORE_DISABLE_MASK));
/* P-Unit bring up */
reg = readl(MCHBAR_REG(BIOS_RESET_CPL));
if (reg == 0xffffffff) {
/* P-unit not found */
debug("Punit MMIO not available\n");
return -ENOENT;
}
/* Set Punit interrupt pin IPIN offset 3D */
dm_pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x2);
/* Set PUINT IRQ to 24 and INTPIN LOCK */
writel(PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
PUINT_THERMAL_DEVICE_IRQ_LOCK,
MCHBAR_REG(PUNIT_THERMAL_DEVICE_IRQ));
/* Stage0 BIOS Reset Complete (RST_CPL) */
enable_bios_reset_cpl();
/*
* Poll for bit 8 to check if PCODE has completed its action in response
* to BIOS Reset complete. We wait here till 1 ms for the bit to get
* set.
*/
start = get_timer(0);
while (!(readl(MCHBAR_REG(BIOS_RESET_CPL)) & PCODE_INIT_DONE)) {
if (get_timer(start) > 1) {
debug("PCODE Init Done timeout\n");
return -ETIMEDOUT;
}
udelay(100);
}
debug("PUNIT init complete\n");
return 0;
}
static int apl_punit_probe(struct udevice *dev)
{
if (spl_phase() == PHASE_SPL)
return punit_init(dev);
return 0;
}
static const struct udevice_id apl_syscon_ids[] = {
{ .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
{ }
};
U_BOOT_DRIVER(syscon_intel_punit) = {
.name = "intel_punit_syscon",
.id = UCLASS_SYSCON,
.of_match = apl_syscon_ids,
.probe = apl_punit_probe,
};

View File

@ -0,0 +1,178 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <binman_sym.h>
#include <dm.h>
#include <spi.h>
#include <spl.h>
#include <spi_flash.h>
#include <asm/fast_spi.h>
#include <asm/spl.h>
#include <asm/arch/cpu.h>
#include <asm/arch/iomap.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
/* This reads the next phase from mapped SPI flash */
static int rom_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
ulong spl_pos = spl_get_image_pos();
ulong spl_size = spl_get_image_size();
struct udevice *dev;
ulong map_base;
size_t map_size;
uint offset;
int ret;
spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
spl_image->entry_point = spl_phase() == PHASE_TPL ?
CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
spl_image->load_addr = spl_image->entry_point;
spl_image->os = IH_OS_U_BOOT;
spl_image->name = "U-Boot";
debug("Reading from mapped SPI %lx, size %lx", spl_pos, spl_size);
if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
if (ret)
return log_msg_ret("spi_flash", ret);
if (!dev)
return log_msg_ret("spi_flash dev", -ENODEV);
ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
if (ret)
return log_msg_ret("mmap", ret);
} else {
ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
&offset);
if (ret)
return ret;
}
spl_pos += map_base & ~0xff000000;
debug(", base %lx, pos %lx\n", map_base, spl_pos);
bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
memcpy((void *)spl_image->load_addr, (void *)spl_pos, spl_size);
cpu_flush_l1d_to_l2();
bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
return 0;
}
SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image);
#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)
static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len,
void *buf)
{
struct spi_flash *flash = dev_get_uclass_priv(dev);
struct mtd_info *mtd = &flash->mtd;
size_t retlen;
return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
}
static int apl_flash_probe(struct udevice *dev)
{
return spi_flash_std_probe(dev);
}
/*
* Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also
* need to allocate the parent_platdata since by the time this function is
* called device_bind() has already gone past that step.
*/
static int apl_flash_bind(struct udevice *dev)
{
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
struct dm_spi_slave_platdata *plat;
struct udevice *spi;
int ret;
ret = uclass_first_device_err(UCLASS_SPI, &spi);
if (ret)
return ret;
dev->parent = spi;
plat = calloc(sizeof(*plat), 1);
if (!plat)
return -ENOMEM;
dev->parent_platdata = plat;
}
return 0;
}
static const struct dm_spi_flash_ops apl_flash_ops = {
.read = apl_flash_std_read,
};
static const struct udevice_id apl_flash_ids[] = {
{ .compatible = "jedec,spi-nor" },
{ }
};
U_BOOT_DRIVER(winbond_w25q128fw) = {
.name = "winbond_w25q128fw",
.id = UCLASS_SPI_FLASH,
.of_match = apl_flash_ids,
.bind = apl_flash_bind,
.probe = apl_flash_probe,
.priv_auto_alloc_size = sizeof(struct spi_flash),
.ops = &apl_flash_ops,
};
/* This uses a SPI flash device to read the next phase */
static int spl_fast_spi_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
ulong spl_pos = spl_get_image_pos();
ulong spl_size = spl_get_image_size();
struct udevice *dev;
int ret;
ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
if (ret)
return ret;
spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
spl_image->entry_point = spl_phase() == PHASE_TPL ?
CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
spl_image->load_addr = spl_image->entry_point;
spl_image->os = IH_OS_U_BOOT;
spl_image->name = "U-Boot";
spl_pos &= ~0xff000000;
debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size);
ret = spi_flash_read_dm(dev, spl_pos, spl_size,
(void *)spl_image->load_addr);
cpu_flush_l1d_to_l2();
if (ret)
return ret;
return 0;
}
SPL_LOAD_IMAGE_METHOD("Fast SPI", 1, BOOT_DEVICE_FAST_SPI,
spl_fast_spi_load_image);
void board_boot_order(u32 *spl_boot_list)
{
bool use_spi_flash = IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH);
if (use_spi_flash) {
spl_boot_list[0] = BOOT_DEVICE_FAST_SPI;
spl_boot_list[1] = BOOT_DEVICE_SPI_MMAP;
} else {
spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
spl_boot_list[1] = BOOT_DEVICE_FAST_SPI;
}
}
#else
void board_boot_order(u32 *spl_boot_list)
{
spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
}
#endif

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2017 Intel Corporation.
* Take from coreboot project file of the same name
*/
#include <common.h>
#include <asm/intel_regs.h>
#include <asm/io.h>
#include <asm/arch/systemagent.h>
void enable_bios_reset_cpl(void)
{
/*
* Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
* that BIOS has initialised memory and power management
*
* The FSP-S does not do this. If we leave this as zero then I believe
* the power-aware interrupts don't work in Linux, and CPU 0 always gets
* the interrupt.
*/
setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3);
}

View File

@ -0,0 +1,133 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Special driver to handle of-platdata
*
* Copyright 2019 Google LLC
*
* Some code from coreboot lpss.c
*/
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
#include <ns16550.h>
#include <spl.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/lpss.h>
/* Low-power Subsystem (LPSS) clock register */
enum {
LPSS_CLOCK_CTL_REG = 0x200,
LPSS_CNT_CLOCK_EN = 1,
LPSS_CNT_CLK_UPDATE = 1U << 31,
LPSS_CLOCK_DIV_N_SHIFT = 16,
LPSS_CLOCK_DIV_N_MASK = 0x7fff << LPSS_CLOCK_DIV_N_SHIFT,
LPSS_CLOCK_DIV_M_SHIFT = 1,
LPSS_CLOCK_DIV_M_MASK = 0x7fff << LPSS_CLOCK_DIV_M_SHIFT,
/* These set the UART input clock speed */
LPSS_UART_CLK_M_VAL = 0x25a,
LPSS_UART_CLK_N_VAL = 0x7fff,
};
static void lpss_clk_update(void *regs, u32 clk_m_val, u32 clk_n_val)
{
u32 clk_sel;
clk_sel = clk_n_val << LPSS_CLOCK_DIV_N_SHIFT |
clk_m_val << LPSS_CLOCK_DIV_M_SHIFT;
clk_sel |= LPSS_CNT_CLK_UPDATE | LPSS_CNT_CLOCK_EN;
writel(clk_sel, regs + LPSS_CLOCK_CTL_REG);
}
static void uart_lpss_init(void *regs)
{
/* Take UART out of reset */
lpss_reset_release(regs);
/* Set M and N divisor inputs and enable clock */
lpss_clk_update(regs, LPSS_UART_CLK_M_VAL, LPSS_UART_CLK_N_VAL);
}
void apl_uart_init(pci_dev_t bdf, ulong base)
{
/* Set UART base address */
pci_x86_write_config(bdf, PCI_BASE_ADDRESS_0, base, PCI_SIZE_32);
/* Enable memory access and bus master */
pci_x86_write_config(bdf, PCI_COMMAND, PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER, PCI_SIZE_32);
uart_lpss_init((void *)base);
}
/*
* This driver uses its own compatible string but almost everything else from
* the standard ns16550 driver. This allows us to provide an of-platdata
* implementation, since the platdata produced by of-platdata does not match
* struct ns16550_platdata.
*
* When running with of-platdata (generally TPL), the platdata is converted to
* something that ns16550 expects. When running withoutof-platdata (SPL, U-Boot
* proper), we use ns16550's ofdata_to_platdata routine.
*/
static int apl_ns16550_probe(struct udevice *dev)
{
struct ns16550_platdata *plat = dev_get_platdata(dev);
if (!CONFIG_IS_ENABLED(PCI))
apl_uart_init(plat->bdf, plat->base);
return ns16550_serial_probe(dev);
}
static int apl_ns16550_ofdata_to_platdata(struct udevice *dev)
{
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_intel_apl_ns16550 *dtplat = dev_get_platdata(dev);
struct ns16550_platdata *plat;
/*
* Convert our platdata to the ns16550's platdata, so we can just use
* that driver
*/
plat = malloc(sizeof(*plat));
if (!plat)
return -ENOMEM;
plat->base = dtplat->early_regs[0];
plat->reg_width = 1;
plat->reg_shift = dtplat->reg_shift;
plat->reg_offset = 0;
plat->clock = dtplat->clock_frequency;
plat->fcr = UART_FCR_DEFVAL;
plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
dev->platdata = plat;
#else
int ret;
ret = ns16550_serial_ofdata_to_platdata(dev);
if (ret)
return ret;
#endif /* OF_PLATDATA */
return 0;
}
static const struct udevice_id apl_ns16550_serial_ids[] = {
{ .compatible = "intel,apl-ns16550" },
{ },
};
U_BOOT_DRIVER(apl_ns16550) = {
.name = "intel_apl_ns16550",
.id = UCLASS_SERIAL,
.of_match = apl_ns16550_serial_ids,
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
.priv_auto_alloc_size = sizeof(struct NS16550),
.ops = &ns16550_serial_ops,
.ofdata_to_platdata = apl_ns16550_ofdata_to_platdata,
.probe = apl_ns16550_probe,
};

View File

@ -83,7 +83,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
if (ret)
return ret;
mrc_cache = mrccache_find_current(&entry);
@ -169,12 +169,14 @@ int dram_init(void)
pei_data->data_to_save);
/* S3 resume: don't save scrambler seed or MRC data */
if (pei_data->boot_mode != SLEEP_STATE_S3) {
struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
/*
* This will be copied to SDRAM in reserve_arch(), then written
* to SPI flash in mrccache_save()
*/
gd->arch.mrc_output = (char *)pei_data->data_to_save;
gd->arch.mrc_output_len = pei_data->data_to_save_size;
mrc->buf = (char *)pei_data->data_to_save;
mrc->len = pei_data->data_to_save_size;
}
gd->arch.pei_meminfo = pei_data->meminfo;

View File

@ -24,5 +24,6 @@ config SYS_COREBOOT
imply CMD_CBFS
imply FS_CBFS
imply CBMEM_CONSOLE
imply X86_TSC_READ_BASE
endif

View File

@ -46,6 +46,7 @@
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_TPL_BUILD
static const char *const x86_vendor_name[] = {
[X86_VENDOR_INTEL] = "Intel",
[X86_VENDOR_CYRIX] = "Cyrix",
@ -58,6 +59,7 @@ static const char *const x86_vendor_name[] = {
[X86_VENDOR_NSC] = "NSC",
[X86_VENDOR_SIS] = "SiS",
};
#endif
int __weak x86_cleanup_before_linux(void)
{
@ -114,6 +116,7 @@ int icache_status(void)
return 1;
}
#ifndef CONFIG_TPL_BUILD
const char *cpu_vendor_name(int vendor)
{
const char *name;
@ -124,6 +127,7 @@ const char *cpu_vendor_name(int vendor)
return name;
}
#endif
char *cpu_get_name(char *name)
{

View File

@ -5,5 +5,7 @@
obj-y += call64.o
obj-y += cpu.o
ifndef CONFIG_TPL_BUILD
obj-y += interrupt.o
endif
obj-y += setjmp.o

View File

@ -21,6 +21,7 @@
#include <common.h>
#include <cpu_func.h>
#include <malloc.h>
#include <spl.h>
#include <asm/control_regs.h>
#include <asm/cpu.h>
#include <asm/mp.h>
@ -58,6 +59,8 @@ struct cpuinfo_x86 {
uint8_t x86_mask;
};
/* gcc 7.3 does not wwant to drop x86_vendors, so use #ifdef */
#ifndef CONFIG_TPL_BUILD
/*
* List of cpu vendor strings along with their normalized
* id values.
@ -78,6 +81,7 @@ static const struct {
{ X86_VENDOR_NSC, "Geode by NSC", },
{ X86_VENDOR_SIS, "SiS SiS SiS ", },
};
#endif
static void load_ds(u32 segment)
{
@ -199,6 +203,7 @@ static inline int test_cyrix_52div(void)
return (unsigned char) (test >> 8) == 0x02;
}
#ifndef CONFIG_TPL_BUILD
/*
* Detect a NexGen CPU running without BIOS hypercode new enough
* to have CPUID. (Thanks to Herbert Oppmann)
@ -219,6 +224,7 @@ static int deep_magic_nexgen_probe(void)
: "=a" (ret) : : "cx", "dx");
return ret;
}
#endif
static bool has_cpuid(void)
{
@ -230,6 +236,7 @@ static bool has_mtrr(void)
return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
}
#ifndef CONFIG_TPL_BUILD
static int build_vendor_name(char *vendor_name)
{
struct cpuid_result result;
@ -242,14 +249,40 @@ static int build_vendor_name(char *vendor_name)
return result.eax;
}
#endif
static void identify_cpu(struct cpu_device_id *cpu)
{
cpu->device = 0; /* fix gcc 4.4.4 warning */
/*
* Do a quick and dirty check to save space - Intel and AMD only and
* just the vendor. This is enough for most TPL code.
*/
if (spl_phase() == PHASE_TPL) {
struct cpuid_result result;
result = cpuid(0x00000000);
switch (result.ecx >> 24) {
case 'l': /* GenuineIntel */
cpu->vendor = X86_VENDOR_INTEL;
break;
case 'D': /* AuthenticAMD */
cpu->vendor = X86_VENDOR_AMD;
break;
default:
cpu->vendor = X86_VENDOR_ANY;
break;
}
return;
}
/* gcc 7.3 does not want to drop x86_vendors, so use #ifdef */
#ifndef CONFIG_TPL_BUILD
char vendor_name[16];
int i;
vendor_name[0] = '\0'; /* Unset */
cpu->device = 0; /* fix gcc 4.4.4 warning */
/* Find the id and vendor_name */
if (!has_cpuid()) {
@ -265,9 +298,8 @@ static void identify_cpu(struct cpu_device_id *cpu)
/* Detect NexGen with old hypercode */
else if (deep_magic_nexgen_probe())
memcpy(vendor_name, "NexGenDriven", 13);
}
if (has_cpuid()) {
int cpuid_level;
} else {
int cpuid_level;
cpuid_level = build_vendor_name(vendor_name);
vendor_name[12] = '\0';
@ -287,6 +319,7 @@ static void identify_cpu(struct cpu_device_id *cpu)
break;
}
}
#endif
}
static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)

View File

@ -8,8 +8,18 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
endif
ifdef CONFIG_INTEL_CAR_CQOS
obj-$(CONFIG_TPL_BUILD) += car2.o
ifndef CONFIG_SPL_BUILD
obj-y += car2_uninit.o
endif
endif
obj-y += cpu.o
obj-y += fast_spi.o
obj-y += lpc.o
obj-y += lpss.o
ifndef CONFIG_TARGET_EFI_APP
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
ifndef CONFIG_$(SPL_)X86_64

View File

@ -0,0 +1,448 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file was modified from the coreboot version.
*
* Copyright (C) 2015-2016 Intel Corp.
*/
#include <config.h>
#include <asm/msr-index.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/processor-flags.h>
#define KiB 1024
#define IS_POWER_OF_2(x) (!((x) & ((x) - 1)))
.global car_init
car_init:
post_code(POST_CAR_START)
/*
* Use the MTRR default type MSR as a proxy for detecting INIT#.
* Reset the system if any known bits are set in that MSR. That is
* an indication of the CPU not being properly reset.
*/
check_for_clean_reset:
mov $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
and $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
cmp $0, %eax
jz no_reset
/* perform warm reset */
movw $IO_PORT_RESET, %dx
movb $(SYS_RST | RST_CPU), %al
outb %al, %dx
no_reset:
post_code(POST_CAR_SIPI)
/* Clear/disable fixed MTRRs */
mov $fixed_mtrr_list_size, %ebx
xor %eax, %eax
xor %edx, %edx
clear_fixed_mtrr:
add $-2, %ebx
movzwl fixed_mtrr_list(%ebx), %ecx
wrmsr
jnz clear_fixed_mtrr
post_code(POST_CAR_MTRR)
/* Figure put how many MTRRs we have, and clear them out */
mov $MTRR_CAP_MSR, %ecx
rdmsr
movzb %al, %ebx /* Number of variable MTRRs */
mov $MTRR_PHYS_BASE_MSR(0), %ecx
xor %eax, %eax
xor %edx, %edx
clear_var_mtrr:
wrmsr
inc %ecx
wrmsr
inc %ecx
dec %ebx
jnz clear_var_mtrr
post_code(POST_CAR_UNCACHEABLE)
/* Configure default memory type to uncacheable (UC) */
mov $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
/* Clear enable bits and set default type to UC */
and $~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
MTRR_DEF_TYPE_FIX_EN), %eax
wrmsr
/*
* Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
* based on the physical address size supported for this processor
* This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
*
* Examples:
* MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing
* MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing
*/
movl $0x80000008, %eax /* Address sizes leaf */
cpuid
sub $32, %al
movzx %al, %eax
xorl %esi, %esi
bts %eax, %esi
dec %esi /* esi <- MTRR_PHYS_MASK_HIGH */
post_code(POST_CAR_BASE_ADDRESS)
#if IS_POWER_OF_2(CONFIG_DCACHE_RAM_SIZE)
/* Configure CAR region as write-back (WB) */
mov $MTRR_PHYS_BASE_MSR(0), %ecx
mov $CONFIG_DCACHE_RAM_BASE, %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr
/* Configure the MTRR mask for the size region */
mov $MTRR_PHYS_MASK(0), %ecx
mov $CONFIG_DCACHE_RAM_SIZE, %eax /* size mask */
dec %eax
not %eax
or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
/* Configure CAR region as write-back (WB) */
mov $MTRR_PHYS_BASE_MSR(0), %ecx
mov $CONFIG_DCACHE_RAM_BASE, %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr
mov $MTRR_PHYS_MASK_MSR(0), %ecx
mov $(512 * KiB), %eax /* size mask */
dec %eax
not %eax
or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
mov $MTRR_PHYS_BASE_MSR(1), %ecx
mov $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr
mov $MTRR_PHYS_MASK_MSR(1), %ecx
mov $(256 * KiB), %eax /* size mask */
dec %eax
not %eax
or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
#else
#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
#endif
post_code(POST_CAR_FILL)
/* Enable variable MTRRs */
mov $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
or $MTRR_DEF_TYPE_EN, %eax
wrmsr
/* Enable caching */
mov %cr0, %eax
and $~(X86_CR0_CD | X86_CR0_NW), %eax
invd
mov %eax, %cr0
#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
jmp car_nem
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
jmp car_cqos
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
jmp car_nem_enhanced
#else
#error "No CAR mechanism selected:
#endif
jmp car_init_ret
fixed_mtrr_list:
.word MTRR_FIX_64K_00000_MSR
.word MTRR_FIX_16K_80000_MSR
.word MTRR_FIX_16K_A0000_MSR
.word MTRR_FIX_4K_C0000_MSR
.word MTRR_FIX_4K_C8000_MSR
.word MTRR_FIX_4K_D0000_MSR
.word MTRR_FIX_4K_D8000_MSR
.word MTRR_FIX_4K_E0000_MSR
.word MTRR_FIX_4K_E8000_MSR
.word MTRR_FIX_4K_F0000_MSR
.word MTRR_FIX_4K_F8000_MSR
fixed_mtrr_list_size = . - fixed_mtrr_list
#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
.global car_nem
car_nem:
/* Disable cache eviction (setup stage) */
mov $MSR_EVICT_CTL, %ecx
rdmsr
or $0x1, %eax
wrmsr
post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */
movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx
xor %eax, %eax
cld
rep stosl
post_code(0x27)
/* Disable cache eviction (run stage) */
mov $MSR_EVICT_CTL, %ecx
rdmsr
or $0x2, %eax
wrmsr
post_code(0x28)
jmp car_init_ret
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
.global car_cqos
car_cqos:
/*
* Create CBM_LEN_MASK based on CBM_LEN
* Get CPUID.(EAX=10H, ECX=2H):EAX.CBM_LEN[bits 4:0]
*/
mov $0x10, %eax
mov $0x2, %ecx
cpuid
and $0x1f, %eax
add $1, %al
mov $1, %ebx
mov %al, %cl
shl %cl, %ebx
sub $1, %ebx
/* Store the CBM_LEN_MASK in mm3 for later use */
movd %ebx, %mm3
/*
* Disable both L1 and L2 prefetcher. For yet-to-understood reason,
* prefetchers slow down filling cache with rep stos in CQOS mode.
*/
mov $MSR_PREFETCH_CTL, %ecx
rdmsr
or $(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
wrmsr
#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
/*
* If CAR size is set to full L2 size, mask is calculated as all-zeros.
* This is not supported by the CPU/uCode.
*/
#error "CQOS CAR may not use whole L2 cache area"
#endif
/* Calculate how many bits to be used for CAR */
xor %edx, %edx
mov $CONFIG_DCACHE_RAM_SIZE, %eax /* dividend */
mov $CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx /* divisor */
div %ecx /* result is in eax */
mov %eax, %ecx /* save to ecx */
mov $1, %ebx
shl %cl, %ebx
sub $1, %ebx /* resulting mask is is in ebx */
/* Set this mask for initial cache fill */
mov $MSR_L2_QOS_MASK(0), %ecx
rdmsr
mov %ebx, %eax
wrmsr
/* Set CLOS selector to 0 */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~MSR_IA32_PQR_ASSOC_MASK, %edx /* select mask 0 */
wrmsr
/* We will need to block CAR region from evicts */
mov $MSR_L2_QOS_MASK(1), %ecx
rdmsr
/* Invert bits that are to be used for cache */
mov %ebx, %eax
xor $~0, %eax /* invert 32 bits */
/*
* Use CBM_LEN_MASK stored in mm3 to set bits based on Capacity Bit
* Mask Length.
*/
movd %mm3, %ebx
and %ebx, %eax
wrmsr
post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */
movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx
xor %eax, %eax
cld
rep stosl
post_code(0x27)
/* Cache is populated. Use mask 1 that will block evicts */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~MSR_IA32_PQR_ASSOC_MASK, %edx /* clear index bits first */
or $1, %edx /* select mask 1 */
wrmsr
/* Enable prefetchers */
mov $MSR_PREFETCH_CTL, %ecx
rdmsr
and $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
wrmsr
post_code(0x28)
jmp car_init_ret
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
.global car_nem_enhanced
car_nem_enhanced:
/* Disable cache eviction (setup stage) */
mov $MSR_EVICT_CTL, %ecx
rdmsr
or $0x1, %eax
wrmsr
post_code(0x26)
/* Create n-way set associativity of cache */
xorl %edi, %edi
find_llc_subleaf:
movl %edi, %ecx
movl $0x04, %eax
cpuid
inc %edi
and $0xe0, %al /* EAX[7:5] = Cache Level */
cmp $0x60, %al /* Check to see if it is LLC */
jnz find_llc_subleaf
/*
* Set MSR 0xC91 IA32_L3_MASK_! = 0xE/0xFE/0xFFE/0xFFFE
* for 4/8/16 way of LLC
*/
shr $22, %ebx
inc %ebx
/* Calculate n-way associativity of LLC */
mov %bl, %cl
/*
* Maximizing RO cacheability while locking in the CAR to a
* single way since that particular way won't be victim candidate
* for evictions.
* This has been done after programing LLC_WAY_MASK_1 MSR
* with desired LLC way as mentioned below.
*
* Hence create Code and Data Size as per request
* Code Size (RO) : Up to 16M
* Data Size (RW) : Up to 256K
*/
movl $0x01, %eax
/*
* LLC Ways -> LLC_WAY_MASK_1:
* 4: 0x000E
* 8: 0x00FE
* 12: 0x0FFE
* 16: 0xFFFE
*
* These MSRs contain one bit per each way of LLC
* - If this bit is '0' - the way is protected from eviction
* - If this bit is '1' - the way is not protected from eviction
*/
shl %cl, %eax
subl $0x02, %eax
movl $MSR_IA32_L3_MASK_1, %ecx
xorl %edx, %edx
wrmsr
/*
* Set MSR 0xC92 IA32_L3_MASK_2 = 0x1
*
* For SKL SOC, data size remains 256K consistently.
* Hence, creating 1-way associative cache for Data
*/
mov $MSR_IA32_L3_MASK_2, %ecx
mov $0x01, %eax
xorl %edx, %edx
wrmsr
/*
* Set MSR_IA32_PQR_ASSOC = 0x02
*
* Possible values:
* 0: Default value, no way mask should be applied
* 1: Apply way mask 1 to LLC
* 2: Apply way mask 2 to LLC
* 3: Shouldn't be use in NEM Mode
*/
movl $MSR_IA32_PQR_ASSOC, %ecx
movl $0x02, %eax
xorl %edx, %edx
wrmsr
movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx
xor %eax, %eax
cld
rep stosl
/*
* Set MSR_IA32_PQR_ASSOC = 0x01
* At this stage we apply LLC_WAY_MASK_1 to the cache.
* i.e. way 0 is protected from eviction.
*/
movl $MSR_IA32_PQR_ASSOC, %ecx
movl $0x01, %eax
xorl %edx, %edx
wrmsr
post_code(0x27)
/*
* Enable No-Eviction Mode Run State by setting
* NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
*/
movl $MSR_EVICT_CTL, %ecx
rdmsr
orl $0x02, %eax
wrmsr
post_code(0x28)
jmp car_init_ret
#endif
#if CONFIG_IS_ENABLED(X86_16BIT_INIT)
_dt_ucode_base_size:
/* These next two fields are filled in by binman */
.globl ucode_base
ucode_base: /* Declared in microcode.h */
.long 0 /* microcode base */
.globl ucode_size
ucode_size: /* Declared in microcode.h */
.long 0 /* microcode size */
.long CONFIG_SYS_MONITOR_BASE /* code region base */
.long CONFIG_SYS_MONITOR_LEN /* code region size */
#endif

View File

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2017 Intel Corp.
* Copyright 2019 Google LLC
* Taken from coreboot file exit_car.S
*/
#include <config.h>
#include <asm/msr-index.h>
#include <asm/mtrr.h>
.text
.global car_uninit
car_uninit:
/*
* Retrieve return address from stack as it will get trashed below if
* execution is utilizing the cache-as-ram stack.
*/
pop %ebx
/* Disable MTRRs */
mov $(MTRR_DEF_TYPE_MSR), %ecx
rdmsr
and $(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
wrmsr
#ifdef CONFIG_INTEL_CAR_NEM
.global car_nem_teardown
car_nem_teardown:
/* invalidate cache contents */
invd
/* Knock down bit 1 then bit 0 of NEM control not combining steps */
mov $(MSR_EVICT_CTL), %ecx
rdmsr
and $(~(1 << 1)), %eax
wrmsr
and $(~(1 << 0)), %eax
wrmsr
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
.global car_cqos_teardown
car_cqos_teardown:
/* Go back to all-evicting mode, set both masks to all-1s */
mov $MSR_L2_QOS_MASK(0), %ecx
rdmsr
mov $~0, %al
wrmsr
mov $MSR_L2_QOS_MASK(1), %ecx
rdmsr
mov $~0, %al
wrmsr
/* Reset CLOS selector to 0 */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~MSR_IA32_PQR_ASSOC_MASK, %edx
wrmsr
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
.global car_nem_enhanced_teardown
car_nem_enhanced_teardown:
/* invalidate cache contents */
invd
/* Knock down bit 1 then bit 0 of NEM control not combining steps */
mov $(MSR_EVICT_CTL), %ecx
rdmsr
and $(~(1 << 1)), %eax
wrmsr
and $(~(1 << 0)), %eax
wrmsr
/* Reset CLOS selector to 0 */
mov $IA32_PQR_ASSOC, %ecx
rdmsr
and $~IA32_PQR_ASSOC_MASK, %edx
wrmsr
#endif
/* Return to caller */
jmp *%ebx

View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <asm/io.h>
#include <asm/cpu_common.h>
#include <asm/fast_spi.h>
#include <asm/pci.h>
/*
* Returns bios_start and fills in size of the BIOS region.
*/
static ulong fast_spi_get_bios_region(struct fast_spi_regs *regs,
uint *bios_size)
{
ulong bios_start, bios_end;
/*
* BIOS_BFPREG provides info about BIOS-Flash Primary Region Base and
* Limit. Base and Limit fields are in units of 4K.
*/
u32 val = readl(&regs->bfp);
bios_start = (val & SPIBAR_BFPREG_PRB_MASK) << 12;
bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
SPIBAR_BFPREG_PRL_SHIFT) + 1) << 12;
*bios_size = bios_end - bios_start;
return bios_start;
}
int fast_spi_get_bios_mmap(pci_dev_t pdev, ulong *map_basep, uint *map_sizep,
uint *offsetp)
{
struct fast_spi_regs *regs;
ulong bar, base, mmio_base;
/* Special case to find mapping without probing the device */
pci_x86_read_config(pdev, PCI_BASE_ADDRESS_0, &bar, PCI_SIZE_32);
mmio_base = bar & PCI_BASE_ADDRESS_MEM_MASK;
regs = (struct fast_spi_regs *)mmio_base;
base = fast_spi_get_bios_region(regs, map_sizep);
*map_basep = (u32)-*map_sizep - base;
*offsetp = base;
return 0;
}
int fast_spi_early_init(pci_dev_t pdev, ulong mmio_base)
{
/* Program Temporary BAR for SPI */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
PCI_SIZE_32);
/* Enable Bus Master and MMIO Space */
pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
/*
* Disable the BIOS write protect so write commands are allowed.
* Enable Prefetching and caching.
*/
pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
SPIBAR_BIOS_CONTROL_EISS |
SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
SPIBAR_BIOS_CONTROL_WPD |
SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
return 0;
}

View File

@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Special driver to handle of-platdata
*
* Copyright 2019 Google LLC
*
* Some code from coreboot lpss.c
*/
#include <common.h>
#include <dm.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/lpss.h>
enum {
LPSS_RESET_CTL_REG = 0x204,
/*
* Bit 1:0 controls LPSS controller reset.
*
* 00 ->LPSS Host Controller is in reset (Reset Asserted)
* 01/10 ->Reserved
* 11 ->LPSS Host Controller is NOT at reset (Reset Released)
*/
LPSS_CNT_RST_RELEASE = 3,
/* Power management control and status register */
PME_CTRL_STATUS = 0x84,
/* Bit 1:0 Powerstate, controls D0 and D3 state */
POWER_STATE_MASK = 3,
};
/* Take controller out of reset */
void lpss_reset_release(void *regs)
{
writel(LPSS_CNT_RST_RELEASE, regs + LPSS_RESET_CTL_REG);
}
void lpss_set_power_state(struct udevice *dev, enum lpss_pwr_state state)
{
dm_pci_clrset_config8(dev, PME_CTRL_STATUS, POWER_STATE_MASK, state);
}

View File

@ -350,14 +350,6 @@ int irq_router_probe(struct udevice *dev)
return 0;
}
ulong write_pirq_routing_table(ulong addr)
{
if (!gd->arch.pirq_routing_table)
return addr;
return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table);
}
static const struct udevice_id irq_router_ids[] = {
{ .compatible = "intel,irq-router" },
{ }
@ -370,8 +362,3 @@ U_BOOT_DRIVER(irq_router_drv) = {
.probe = irq_router_probe,
.priv_auto_alloc_size = sizeof(struct irq_router),
};
UCLASS_DRIVER(irq) = {
.id = UCLASS_IRQ,
.name = "irq",
};

View File

@ -116,7 +116,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
ret = read_seed_from_cmos(pei_data);
if (ret)
return ret;
ret = mrccache_get_region(NULL, &entry);
ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
if (ret)
return ret;
mrc_cache = mrccache_find_current(&entry);
@ -538,12 +538,14 @@ int dram_init(void)
/* S3 resume: don't save scrambler seed or MRC data */
if (pei_data->boot_mode != PEI_BOOT_RESUME) {
struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
/*
* This will be copied to SDRAM in reserve_arch(), then written
* to SPI flash in mrccache_save()
*/
gd->arch.mrc_output = (char *)pei_data->mrc_output;
gd->arch.mrc_output_len = pei_data->mrc_output_len;
mrc->buf = (char *)pei_data->mrc_output;
mrc->len = pei_data->mrc_output_len;
ret = write_seeds_to_cmos(pei_data);
if (ret)
debug("Failed to write seeds to CMOS: %d\n", ret);

View File

@ -418,69 +418,6 @@ static int init_bsp(struct udevice **devp)
return 0;
}
#ifdef CONFIG_QFW
static int qemu_cpu_fixup(void)
{
int ret;
int cpu_num;
int cpu_online;
struct udevice *dev, *pdev;
struct cpu_platdata *plat;
char *cpu;
/* first we need to find '/cpus' */
for (device_find_first_child(dm_root(), &pdev);
pdev;
device_find_next_child(&pdev)) {
if (!strcmp(pdev->name, "cpus"))
break;
}
if (!pdev) {
printf("unable to find cpus device\n");
return -ENODEV;
}
/* calculate cpus that are already bound */
cpu_num = 0;
for (uclass_find_first_device(UCLASS_CPU, &dev);
dev;
uclass_find_next_device(&dev)) {
cpu_num++;
}
/* get actual cpu number */
cpu_online = qemu_fwcfg_online_cpus();
if (cpu_online < 0) {
printf("unable to get online cpu number: %d\n", cpu_online);
return cpu_online;
}
/* bind addtional cpus */
dev = NULL;
for (; cpu_num < cpu_online; cpu_num++) {
/*
* allocate device name here as device_bind_driver() does
* not copy device name, 8 bytes are enough for
* sizeof("cpu@") + 3 digits cpu number + '\0'
*/
cpu = malloc(8);
if (!cpu) {
printf("unable to allocate device name\n");
return -ENOMEM;
}
sprintf(cpu, "cpu@%d", cpu_num);
ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev);
if (ret) {
printf("binding cpu@%d failed: %d\n", cpu_num, ret);
return ret;
}
plat = dev_get_parent_platdata(dev);
plat->cpu_id = cpu_num;
}
return 0;
}
#endif
int mp_init(struct mp_params *p)
{
int num_aps;
@ -494,11 +431,11 @@ int mp_init(struct mp_params *p)
if (ret)
return ret;
#ifdef CONFIG_QFW
ret = qemu_cpu_fixup();
if (ret)
return ret;
#endif
if (IS_ENABLED(CONFIG_QFW)) {
ret = qemu_cpu_fixup();
if (ret)
return ret;
}
ret = init_bsp(&cpu);
if (ret) {

73
arch/x86/cpu/qfw_cpu.c Normal file
View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015 Google, Inc
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <qfw.h>
#include <dm/lists.h>
#include <dm/uclass-internal.h>
#include <dm/root.h>
int qemu_cpu_fixup(void)
{
int ret;
int cpu_num;
int cpu_online;
struct udevice *dev, *pdev;
struct cpu_platdata *plat;
char *cpu;
/* first we need to find '/cpus' */
for (device_find_first_child(dm_root(), &pdev);
pdev;
device_find_next_child(&pdev)) {
if (!strcmp(pdev->name, "cpus"))
break;
}
if (!pdev) {
printf("unable to find cpus device\n");
return -ENODEV;
}
/* calculate cpus that are already bound */
cpu_num = 0;
for (uclass_find_first_device(UCLASS_CPU, &dev);
dev;
uclass_find_next_device(&dev)) {
cpu_num++;
}
/* get actual cpu number */
cpu_online = qemu_fwcfg_online_cpus();
if (cpu_online < 0) {
printf("unable to get online cpu number: %d\n", cpu_online);
return cpu_online;
}
/* bind addtional cpus */
dev = NULL;
for (; cpu_num < cpu_online; cpu_num++) {
/*
* allocate device name here as device_bind_driver() does
* not copy device name, 8 bytes are enough for
* sizeof("cpu@") + 3 digits cpu number + '\0'
*/
cpu = malloc(8);
if (!cpu) {
printf("unable to allocate device name\n");
return -ENOMEM;
}
sprintf(cpu, "cpu@%d", cpu_num);
ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev);
if (ret) {
printf("binding cpu@%d failed: %d\n", cpu_num, ret);
return ret;
}
plat = dev_get_parent_platdata(dev);
plat->cpu_id = cpu_num;
}
return 0;
}

View File

@ -24,7 +24,7 @@ static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
if (ret)
return ret;
@ -154,9 +154,11 @@ int dram_init(void)
#ifdef CONFIG_ENABLE_MRC_CACHE
cache = malloc(sizeof(struct mrc_timings));
if (cache) {
struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
gd->arch.mrc_output = cache;
gd->arch.mrc_output_len = sizeof(struct mrc_timings);
mrc->buf = cache;
mrc->len = sizeof(struct mrc_timings);
}
#endif

View File

@ -17,3 +17,4 @@ config SYS_SLIMBOOTLOADER
imply USB_EHCI_HCD
imply USB_XHCI_HCD
imply E1000
imply X86_TSC_READ_BASE

View File

@ -17,7 +17,10 @@ SECTIONS
. = IMAGE_TEXT_BASE; /* Location of bootcode in flash */
__text_start = .;
.text : { *(.text*); }
.text : {
__image_copy_start = .;
*(.text*);
}
. = ALIGN(4);

View File

@ -2,6 +2,7 @@
dtb-y += bayleybay.dtb \
cherryhill.dtb \
chromebook_coral.dtb \
chromebook_link.dtb \
chromebox_panther.dtb \
chromebook_samus.dtb \

View File

@ -0,0 +1,831 @@
/* SPDX-License-Identifier: GPL-2.0 */
/dts-v1/;
#include <dt-bindings/gpio/x86-gpio.h>
/include/ "skeleton.dtsi"
/include/ "keyboard.dtsi"
/include/ "reset.dtsi"
/include/ "rtc.dtsi"
/include/ "tsc_timer.dtsi"
#ifdef CONFIG_CHROMEOS
#include "chromeos-x86.dtsi"
#include "flashmap-x86-ro.dtsi"
#include "flashmap-16mb-rw.dtsi"
#endif
#include <asm/intel_pinctrl_defs.h>
#include <asm/arch-apollolake/cpu.h>
#include <asm/arch-apollolake/gpio.h>
#include <asm/arch-apollolake/iomap.h>
#include <asm/arch-apollolake/pm.h>
/ {
model = "Google Coral";
compatible = "google,coral", "intel,apollolake";
aliases {
cros-ec0 = &cros_ec;
fsp = &fsp_s;
spi0 = &spi;
};
config {
silent_console = <0>;
};
chosen {
stdout-path = &serial;
};
cpus {
u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
u-boot,dm-pre-reloc;
device_type = "cpu";
compatible = "intel,apl-cpu";
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "intel,apl-cpu";
reg = <1>;
intel,apic-id = <2>;
};
cpu@2 {
device_type = "cpu";
compatible = "intel,apl-cpu";
reg = <2>;
intel,apic-id = <4>;
};
cpu@3 {
device_type = "cpu";
compatible = "intel,apl-cpu";
reg = <3>;
intel,apic-id = <6>;
};
};
keyboard {
intel,duplicate-por;
};
pci {
compatible = "pci-x86";
#address-cells = <3>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0 0x10000000
0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000
0x01000000 0x0 0x1000 0x1000 0 0xefff>;
u-boot,skip-auto-config-until-reloc;
host_bridge: host-bridge@0,0 {
u-boot,dm-pre-reloc;
reg = <0x00000000 0 0 0 0>;
compatible = "intel,apl-hostbridge";
pciex-region-size = <0x10000000>;
/*
* Parameters used by the FSP-S binary blob. This is
* really unfortunate since these parameters mostly
* relate to drivers but we need them in one place. We
* could put them in the driver nodes easily, but then
* would have to scan each node to find them. So just
* dump them here for now.
*/
fsp_s: fsp-s {
};
};
punit@0,1 {
u-boot,dm-pre-reloc;
reg = <0x00000800 0 0 0 0>;
compatible = "intel,apl-punit";
};
p2sb: p2sb@d,0 {
u-boot,dm-pre-reloc;
reg = <0x02006810 0 0 0 0>;
compatible = "intel,apl-p2sb";
early-regs = <IOMAP_P2SB_BAR 0x100000>;
n {
compatible = "intel,apl-pinctrl";
u-boot,dm-pre-reloc;
intel,p2sb-port-id = <PID_GPIO_N>;
gpio_n: gpio-n {
compatible = "intel,gpio";
u-boot,dm-pre-reloc;
gpio-controller;
#gpio-cells = <2>;
};
};
nw {
u-boot,dm-pre-reloc;
compatible = "intel,apl-pinctrl";
intel,p2sb-port-id = <PID_GPIO_NW>;
#gpio-cells = <2>;
gpio_nw: gpio-nw {
compatible = "intel,gpio";
u-boot,dm-pre-reloc;
gpio-controller;
#gpio-cells = <2>;
};
};
w {
u-boot,dm-pre-reloc;
compatible = "intel,apl-pinctrl";
intel,p2sb-port-id = <PID_GPIO_W>;
#gpio-cells = <2>;
gpio_w: gpio-w {
compatible = "intel,gpio";
u-boot,dm-pre-reloc;
gpio-controller;
#gpio-cells = <2>;
};
};
sw {
u-boot,dm-pre-reloc;
compatible = "intel,apl-pinctrl";
intel,p2sb-port-id = <PID_GPIO_SW>;
#gpio-cells = <2>;
gpio_sw: gpio-sw {
compatible = "intel,gpio";
u-boot,dm-pre-reloc;
gpio-controller;
#gpio-cells = <2>;
};
};
itss {
u-boot,dm-pre-reloc;
compatible = "intel,apl-itss";
intel,p2sb-port-id = <PID_ITSS>;
intel,pmc-routes = <
PMC_GPE_SW_31_0 GPIO_GPE_SW_31_0
PMC_GPE_SW_63_32 GPIO_GPE_SW_63_32
PMC_GPE_NW_31_0 GPIO_GPE_NW_31_0
PMC_GPE_NW_63_32 GPIO_GPE_NW_63_32
PMC_GPE_NW_95_64 GPIO_GPE_NW_95_64
PMC_GPE_N_31_0 GPIO_GPE_N_31_0
PMC_GPE_N_63_32 GPIO_GPE_N_63_32
PMC_GPE_W_31_0 GPIO_GPE_W_31_0>;
};
};
pmc@d,1 {
u-boot,dm-pre-reloc;
reg = <0x6900 0 0 0 0>;
/*
* Values for BAR0, BAR2 and ACPI_BASE for when PCI
* auto-configure is not available
*/
early-regs = <0xfe042000 0x2000
0xfe044000 0x2000
IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>;
compatible = "intel,apl-pmc";
gpe0-dwx-mask = <0xf>;
gpe0-dwx-shift-base = <4>;
/*
* GPE configuration
* Note that GPE events called out in ASL code rely on
* this route, i.e., if this route changes then the
* affected GPE * offset bits also need to be changed.
* This sets the PMC register GPE_CFG fields.
*/
gpe0-dw = <PMC_GPE_N_31_0
PMC_GPE_N_63_32
PMC_GPE_SW_31_0>;
gpe0-sts = <0x20>;
gpe0-en = <0x30>;
};
spi: fast-spi@d,2 {
u-boot,dm-pre-reloc;
reg = <0x02006a10 0 0 0 0>;
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,fast-spi";
early-regs = <IOMAP_SPI_BASE 0x1000>;
intel,hardware-seq = <1>;
fwstore_spi: spi-flash@0 {
#size-cells = <1>;
#address-cells = <1>;
u-boot,dm-pre-reloc;
reg = <0>;
compatible = "winbond,w25q128fw",
"jedec,spi-nor";
rw-mrc-cache {
label = "rw-mrc-cache";
reg = <0x008e0000 0x00010000>;
u-boot,dm-pre-reloc;
};
rw-var-mrc-cache {
label = "rw-mrc-cache";
reg = <0x008f0000 0x0001000>;
u-boot,dm-pre-reloc;
};
};
};
serial: serial@18,2 {
reg = <0x0200c210 0 0 0 0>;
u-boot,dm-pre-reloc;
compatible = "intel,apl-ns16550";
early-regs = <0xde000000 0x20>;
reg-shift = <2>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
pch: pch@1f,0 {
reg = <0x0000f800 0 0 0 0>;
compatible = "intel,apl-pch";
u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <1>;
lpc {
compatible = "intel,apl-lpc";
#address-cells = <1>;
#size-cells = <0>;
u-boot,dm-pre-reloc;
cros_ec: cros-ec {
u-boot,dm-pre-reloc;
compatible = "google,cros-ec-lpc";
reg = <0x204 1 0x200 1 0x880 0x80>;
/*
* Describes the flash memory within
* the EC
*/
#address-cells = <1>;
#size-cells = <1>;
flash@8000000 {
reg = <0x08000000 0x20000>;
erase-value = <0xff>;
};
};
};
};
};
};
&host_bridge {
/*
* PL1 override 12000 mW: the energy calculation is wrong with the
* current VR solution. Experiments show that SoC TDP max (6W) can be
* reached when RAPL PL1 is set to 12W. Set RAPL PL2 to 15W.
*/
tdp-pl-override-mw = <12000 15000>;
early-pads = <
/* These two are for the debug UART */
GPIO_46 /* UART2 RX */
(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
(PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
GPIO_47 /* UART2 TX */
(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
(PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
GPIO_75 /* I2S1_BCLK -- PCH_WP */
(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP)
(PAD_CFG1_PULL_UP_20K | PAD_CFG1_IOSSTATE_TXD_RXE)
/* I2C2 - TPM */
GPIO_128 /* LPSS_I2C2_SDA */
(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
(PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
GPIO_129 /* LPSS_I2C2_SCL */
(PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP)
(PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
GPIO_28 /* TPM IRQ */
(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP |
PAD_CFG0_TX_DISABLE | PAD_CFG0_ROUTE_IOAPIC |
PAD_CFG0_TRIG_LEVEL | PAD_CFG0_RX_POL_INVERT)
(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TXD_RXE)
/*
* WLAN_PE_RST - default to deasserted just in case FSP
* misbehaves
*/
GPIO_122 /* SIO_SPI_2_RXD */
(PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP |
PAD_CFG0_RX_DISABLE | 0)
(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TX_LAST_RXE)
/* LPC */
PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1) /* LPC_SERIRQ */
PAD_CFG_NF(LPC_CLKOUT0, NONE, DEEP, NF1) /* LPC_CLKOUT0 */
PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1)
PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1) /* LPC_AD0 */
PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1) /* LPC_AD1 */
PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1) /* LPC_AD2 */
PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1) /* LPC_AD3 */
PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */
PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */
>;
lpddr4-swizzle = /bits/ 8 <
/* LP4_PHYS_CH0A */
/* DQA[0:7] pins of LPDDR4 module */
6 7 5 4 3 1 0 2
/* DQA[8:15] pins of LPDDR4 module */
12 10 11 13 14 8 9 15
/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
16 22 23 20 18 17 19 21
/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
30 28 29 25 24 26 27 31
/* LP4_PHYS_CH0B */
/* DQA[0:7] pins of LPDDR4 module */
7 3 5 2 6 0 1 4
/* DQA[8:15] pins of LPDDR4 module */
9 14 12 13 10 11 8 15
/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
20 22 23 16 19 17 18 21
/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
28 24 26 27 29 30 31 25
/* LP4_PHYS_CH1A */
/* DQA[0:7] pins of LPDDR4 module */
2 1 6 7 5 4 3 0
/* DQA[8:15] pins of LPDDR4 module */
11 10 8 9 12 15 13 14
/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
17 23 19 16 21 22 20 18
/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
31 29 26 25 28 27 24 30
/* LP4_PHYS_CH1B */
/* DQA[0:7] pins of LPDDR4 module */
4 3 7 5 6 1 0 2
/* DQA[8:15] pins of LPDDR4 module */
15 9 8 11 14 13 12 10
/* DQB[0:7] pins of LPDDR4 module with offset of 16 */
20 23 22 21 18 19 16 17
/* DQB[7:15] pins of LPDDR4 module with offset of 16 */
25 28 30 31 26 27 24 29>;
};
&fsp_s {
u-boot,dm-pre-proper;
/* Disable unused clkreq of PCIe root ports */
pcie-rp-clkreq-pin = /bits/ 8 <0 /* wifi/bt */
CLKREQ_DISABLED
CLKREQ_DISABLED
CLKREQ_DISABLED
CLKREQ_DISABLED
CLKREQ_DISABLED>;
/*
* GPIO for PERST_0
* If the Board has PERST_0 signal, assign the GPIO
* If the Board does not have PERST_0, assign GPIO_PRT0_UDEF
*
* This are not used yet, so comment them out for now.
*
* prt0-gpio = <GPIO_122>;
*
* GPIO for SD card detect
* sdcard-cd-gpio = <GPIO_177>;
*/
/*
* Order is emmc-tx-data-cntl1, emmc-tx-data-cntl2,
* emmc-rx-cmd-data-cntl1, emmc-rx-cmd-data-cntl2
*
* EMMC TX DATA Delay 1
* Refer to EDS-Vol2-22.3
* [14:8] steps of delay for HS400, each 125ps
* [6:0] steps of delay for SDR104/HS200, each 125ps
/*
* EMMC TX DATA Delay 2
* Refer to EDS-Vol2-22.3.
* [30:24] steps of delay for SDR50, each 125ps
* [22:16] steps of delay for DDR50, each 125ps
* [14:8] steps of delay for SDR25/HS50, each 125ps
* [6:0] steps of delay for SDR12, each 125ps
*/
/*
* EMMC RX CMD/DATA Delay 1
* Refer to EDS-Vol2-22.3.
* [30:24] steps of delay for SDR50, each 125ps
* [22:16] steps of delay for DDR50, each 125ps
* [14:8] steps of delay for SDR25/HS50, each 125ps
* [6:0] steps of delay for SDR12, each 125ps
*/
/*
* EMMC RX CMD/DATA Delay 2
* Refer to EDS-Vol2-22.3.
* [17:16] stands for Rx Clock before Output Buffer
* [14:8] steps of delay for Auto Tuning Mode, each 125ps
* [6:0] steps of delay for HS200, each 125ps
*/
emmc = <0x0c16 0x28162828 0x00181717 0x10008>;
/* Enable DPTF */
dptf-enable;
/* Enable Audio Clock and Power gating */
hdaudio-clk-gate-enable;
hdaudio-pwr-gate-enable;
hdaudio-bios-config-lockdown;
/* Enable lpss s0ix */
lpss-s0ix-enable;
/*
* TODO(sjg@chromium.org): Move this to the I2C nodes
* Intel Common SoC Config
*+-------------------+---------------------------+
*| Field | Value |
*+-------------------+---------------------------+
*| I2C0 | Audio |
*| I2C2 | TPM |
*| I2C3 | Touchscreen |
*| I2C4 | Trackpad |
*| I2C5 | Digitizer |
*+-------------------+---------------------------+
*
common_soc_config" = "{
.i2c[0] = {
.speed = I2C_SPEED_FAST,
.rise-time-ns = 104,
.fall-time-ns = 52,
},
.i2c[2] = {
.early_init = 1,
.speed = I2C_SPEED_FAST,
.rise-time-ns = 57,
.fall-time-ns = 28,
},
.i2c[3] = {
.speed = I2C_SPEED_FAST,
.rise-time-ns = 76,
.fall-time-ns = 164,
},
.i2c[4] = {
.speed = I2C_SPEED_FAST,
.rise-time-ns = 114,
.fall-time-ns = 164,
.data_hold_time_ns = 350,
},
.i2c[5] = {
.speed = I2C_SPEED_FAST,
.rise-time-ns = 152,
.fall-time-ns = 30,
},
}"
*/
/* Minimum SLP S3 assertion width 28ms */
slp-s3-assertion-width-usecs = <28000>;
pads = <
/* PCIE_WAKE[0:3]_N */
PAD_CFG_GPI_SCI_LOW(GPIO_205, UP_20K, DEEP, EDGE_SINGLE) /* WLAN */
PAD_CFG_GPI(GPIO_206, UP_20K, DEEP) /* Unused */
PAD_CFG_GPI(GPIO_207, UP_20K, DEEP) /* Unused */
PAD_CFG_GPI(GPIO_208, UP_20K, DEEP) /* Unused */
/* EMMC interface */
PAD_CFG_NF(GPIO_156, DN_20K, DEEP, NF1) /* EMMC_CLK */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_157, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D0 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_158, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D1 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_159, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D2 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_160, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D3 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_161, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D4 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_162, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D5 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_163, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D6 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_164, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D7 */
PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_165, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_CMD */
PAD_CFG_NF(GPIO_182, DN_20K, DEEP, NF1) /* EMMC_RCLK */
/* SDIO -- unused */
PAD_CFG_GPI(GPIO_166, UP_20K, DEEP) /* SDIO_CLK */
PAD_CFG_GPI(GPIO_167, UP_20K, DEEP) /* SDIO_D0 */
/* Configure SDIO to enable power gating */
PAD_CFG_NF(GPIO_168, UP_20K, DEEP, NF1) /* SDIO_D1 */
PAD_CFG_GPI(GPIO_169, UP_20K, DEEP) /* SDIO_D2 */
PAD_CFG_GPI(GPIO_170, UP_20K, DEEP) /* SDIO_D3 */
PAD_CFG_GPI(GPIO_171, UP_20K, DEEP) /* SDIO_CMD */
/* SDCARD */
/* Pull down clock by 20K */
PAD_CFG_NF(GPIO_172, DN_20K, DEEP, NF1) /* SDCARD_CLK */
PAD_CFG_NF(GPIO_173, UP_20K, DEEP, NF1) /* SDCARD_D0 */
PAD_CFG_NF(GPIO_174, UP_20K, DEEP, NF1) /* SDCARD_D1 */
PAD_CFG_NF(GPIO_175, UP_20K, DEEP, NF1) /* SDCARD_D2 */
PAD_CFG_NF(GPIO_176, UP_20K, DEEP, NF1) /* SDCARD_D3 */
/* Card detect is active LOW with external pull up */
PAD_CFG_NF(GPIO_177, NONE, DEEP, NF1) /* SDCARD_CD_N */
PAD_CFG_NF(GPIO_178, UP_20K, DEEP, NF1) /* SDCARD_CMD */
/* CLK feedback, internal signal, needs 20K pull down */
PAD_CFG_NF(GPIO_179, DN_20K, DEEP, NF1) /* SDCARD_CLK_FB */
/* No h/w write proect for uSD cards, pull down by 20K */
PAD_CFG_NF(GPIO_186, DN_20K, DEEP, NF1) /* SDCARD_LVL_WP */
/* EN_SD_SOCKET_PWR_L for SD slot power control. Default on */
PAD_CFG_GPO(GPIO_183, 0, DEEP) /* SDIO_PWR_DOWN_N */
/* SMBus -- unused */
PAD_CFG_GPI(SMB_ALERTB, UP_20K, DEEP) /* SMB_ALERT _N */
PAD_CFG_GPI(SMB_CLK, UP_20K, DEEP) /* SMB_CLK */
PAD_CFG_GPI(SMB_DATA, UP_20K, DEEP) /* SMB_DATA */
/* LPC */
PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1) /* LPC_SERIRQ */
PAD_CFG_NF(LPC_CLKOUT0, NONE, DEEP, NF1) /* LPC_CLKOUT0 */
PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1)
PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1) /* LPC_AD0 */
PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1) /* LPC_AD1 */
PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1) /* LPC_AD2 */
PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1) /* LPC_AD3 */
PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */
PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */
/* I2C0 - Audio */
PAD_CFG_NF(GPIO_124, UP_2K, DEEP, NF1) /* LPSS_I2C0_SDA */
PAD_CFG_NF(GPIO_125, UP_2K, DEEP, NF1) /* LPSS_I2C0_SCL */
/* I2C1 - NFC with external pulls */
PAD_CFG_NF(GPIO_126, NONE, DEEP, NF1) /* LPSS_I2C1_SDA */
PAD_CFG_NF(GPIO_127, NONE, DEEP, NF1) /* LPSS_I2C1_SCL */
/* I2C2 - TPM */
PAD_CFG_NF(GPIO_128, UP_2K, DEEP, NF1) /* LPSS_I2C2_SDA */
PAD_CFG_NF(GPIO_129, UP_2K, DEEP, NF1) /* LPSS_I2C2_SCL */
/* I2C3 - touch */
PAD_CFG_NF(GPIO_130, UP_2K, DEEP, NF1) /* LPSS_I2C3_SDA */
PAD_CFG_NF(GPIO_131, UP_2K, DEEP, NF1) /* LPSS_I2C3_SCL */
/* I2C4 - trackpad */
/* LPSS_I2C4_SDA */
PAD_CFG_NF_IOSSTATE(GPIO_132, UP_2K, DEEP, NF1, HIZCRX1)
/* LPSS_I2C4_SCL */
PAD_CFG_NF_IOSSTATE(GPIO_133, UP_2K, DEEP, NF1, HIZCRX1)
/* I2C5 -- pen with external pulls */
PAD_CFG_NF(GPIO_134, NONE, DEEP, NF1) /* LPSS_I2C5_SDA */
PAD_CFG_NF(GPIO_135, NONE, DEEP, NF1) /* LPSS_I2C5_SCL */
/* I2C6-7 -- unused */
PAD_CFG_GPI(GPIO_136, UP_20K, DEEP) /* LPSS_I2C6_SDA */
PAD_CFG_GPI(GPIO_137, UP_20K, DEEP) /* LPSS_I2C6_SCL */
PAD_CFG_GPI(GPIO_138, UP_20K, DEEP) /* LPSS_I2C7_SDA */
PAD_CFG_GPI(GPIO_139, UP_20K, DEEP) /* LPSS_I2C7_SCL */
/* Audio Amp - I2S6 */
PAD_CFG_NF(GPIO_146, NATIVE, DEEP, NF2) /* ISH_GPIO_0 - I2S6_BCLK */
PAD_CFG_NF(GPIO_147, NATIVE, DEEP, NF2) /* ISH_GPIO_1 - I2S6_WS_SYNC */
PAD_CFG_GPI(GPIO_148, UP_20K, DEEP) /* ISH_GPIO_2 - unused */
PAD_CFG_NF(GPIO_149, NATIVE, DEEP, NF2) /* ISH_GPIO_3 - I2S6_SDO */
/* NFC Reset */
PAD_CFG_GPO(GPIO_150, 1, DEEP) /* ISH_GPIO_4 */
PAD_CFG_GPI(GPIO_151, UP_20K, DEEP) /* ISH_GPIO_5 - unused */
/* Touch enable */
PAD_CFG_GPO(GPIO_152, 1, DEEP) /* ISH_GPIO_6 */
PAD_CFG_GPI(GPIO_153, UP_20K, DEEP) /* ISH_GPIO_7 - unused */
PAD_CFG_GPI(GPIO_154, UP_20K, DEEP) /* ISH_GPIO_8 - unused */
PAD_CFG_GPI(GPIO_155, UP_20K, DEEP) /* ISH_GPIO_9 - unused */
/* PCIE_CLKREQ[0:3]_N */
PAD_CFG_NF(GPIO_209, NONE, DEEP, NF1) /* WLAN with external pull */
PAD_CFG_GPI(GPIO_210, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_211, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_212, UP_20K, DEEP) /* unused */
/* OSC_CLK_OUT_[0:4] -- unused */
PAD_CFG_GPI(OSC_CLK_OUT_0, UP_20K, DEEP)
PAD_CFG_GPI(OSC_CLK_OUT_1, UP_20K, DEEP)
PAD_CFG_GPI(OSC_CLK_OUT_2, UP_20K, DEEP)
PAD_CFG_GPI(OSC_CLK_OUT_3, UP_20K, DEEP)
PAD_CFG_GPI(OSC_CLK_OUT_4, UP_20K, DEEP)
/* PMU Signals */
PAD_CFG_GPI(PMU_AC_PRESENT, UP_20K, DEEP) /* PMU_AC_PRESENT - unused */
PAD_CFG_NF(PMU_BATLOW_B, UP_20K, DEEP, NF1) /* PMU_BATLOW_N */
PAD_CFG_NF(PMU_PLTRST_B, NONE, DEEP, NF1) /* PMU_PLTRST_N */
PAD_CFG_NF(PMU_PWRBTN_B, UP_20K, DEEP, NF1) /* PMU_PWRBTN_N */
PAD_CFG_NF(PMU_RESETBUTTON_B, NONE, DEEP, NF1) /* PMU_RSTBTN_N */
PAD_CFG_NF_IOSSTATE(PMU_SLP_S0_B, NONE, DEEP, NF1, IGNORE) /* PMU_SLP_S0_N */
PAD_CFG_NF(PMU_SLP_S3_B, NONE, DEEP, NF1) /* PMU_SLP_S3_N */
PAD_CFG_NF(PMU_SLP_S4_B, NONE, DEEP, NF1) /* PMU_SLP_S4_N */
PAD_CFG_NF(PMU_SUSCLK, NONE, DEEP, NF1) /* PMU_SUSCLK */
PAD_CFG_GPO(PMU_WAKE_B, 1, DEEP) /* EN_PP3300_EMMC */
PAD_CFG_NF(SUS_STAT_B, NONE, DEEP, NF1) /* SUS_STAT_N */
PAD_CFG_NF(SUSPWRDNACK, NONE, DEEP, NF1) /* SUSPWRDNACK */
/* DDI[0:1] SDA and SCL -- unused */
PAD_CFG_GPI(GPIO_187, UP_20K, DEEP) /* HV_DDI0_DDC_SDA */
PAD_CFG_GPI(GPIO_188, UP_20K, DEEP) /* HV_DDI0_DDC_SCL */
PAD_CFG_GPI(GPIO_189, UP_20K, DEEP) /* HV_DDI1_DDC_SDA */
PAD_CFG_GPI(GPIO_190, UP_20K, DEEP) /* HV_DDI1_DDC_SCL */
/* MIPI I2C -- unused */
PAD_CFG_GPI(GPIO_191, UP_20K, DEEP) /* MIPI_I2C_SDA */
PAD_CFG_GPI(GPIO_192, UP_20K, DEEP) /* MIPI_I2C_SCL */
/* Panel 0 control */
PAD_CFG_NF(GPIO_193, NATIVE, DEEP, NF1) /* PNL0_VDDEN */
PAD_CFG_NF(GPIO_194, NATIVE, DEEP, NF1) /* PNL0_BKLTEN */
PAD_CFG_NF(GPIO_195, NATIVE, DEEP, NF1) /* PNL0_BKLTCTL */
/* Panel 1 control -- unused */
PAD_CFG_NF(GPIO_196, NATIVE, DEEP, NF1) /* PNL1_VDDEN */
PAD_CFG_NF(GPIO_197, NATIVE, DEEP, NF1) /* PNL1_BKLTEN */
PAD_CFG_NF(GPIO_198, NATIVE, DEEP, NF1) /* PNL1_BKLTCTL */
/* Hot plug detect */
PAD_CFG_NF(GPIO_199, UP_20K, DEEP, NF2) /* HV_DDI1_HPD */
PAD_CFG_NF(GPIO_200, UP_20K, DEEP, NF2) /* HV_DDI0_HPD */
/* MDSI signals -- unused */
PAD_CFG_GPI(GPIO_201, UP_20K, DEEP) /* MDSI_A_TE */
PAD_CFG_GPI(GPIO_202, UP_20K, DEEP) /* MDSI_A_TE */
/* USB overcurrent pins */
PAD_CFG_NF(GPIO_203, UP_20K, DEEP, NF1) /* USB_OC0_N */
PAD_CFG_NF(GPIO_204, UP_20K, DEEP, NF1) /* USB_OC1_N */
/* PMC SPI -- almost entirely unused */
PAD_CFG_GPI(PMC_SPI_FS0, UP_20K, DEEP)
PAD_CFG_NF(PMC_SPI_FS1, UP_20K, DEEP, NF2) /* HV_DDI2_HPD -- EDP HPD */
PAD_CFG_GPI(PMC_SPI_FS2, UP_20K, DEEP)
PAD_CFG_GPI(PMC_SPI_RXD, UP_20K, DEEP)
PAD_CFG_GPI(PMC_SPI_TXD, UP_20K, DEEP)
PAD_CFG_GPI(PMC_SPI_CLK, UP_20K, DEEP)
/* PMIC Signals Unused signals related to an old PMIC interface */
PAD_CFG_NF_IOSSTATE(PMIC_RESET_B, NATIVE, DEEP, NF1, IGNORE) /* PMIC_RESET_B */
PAD_CFG_GPI(GPIO_213, NONE, DEEP) /* unused external pull */
PAD_CFG_GPI(GPIO_214, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_215, UP_20K, DEEP) /* unused */
PAD_CFG_NF(PMIC_THERMTRIP_B, UP_20K, DEEP, NF1) /* THERMTRIP_N */
PAD_CFG_GPI(PMIC_STDBY, UP_20K, DEEP) /* unused */
PAD_CFG_NF(PROCHOT_B, UP_20K, DEEP, NF1) /* PROCHOT_N */
PAD_CFG_NF(PMIC_I2C_SCL, UP_1K, DEEP, NF1) /* PMIC_I2C_SCL */
PAD_CFG_NF(PMIC_I2C_SDA, UP_1K, DEEP, NF1) /* PMIC_I2C_SDA */
/* I2S1 -- largely unused */
PAD_CFG_GPI(GPIO_74, UP_20K, DEEP) /* I2S1_MCLK */
PAD_CFG_GPI(GPIO_75, UP_20K, DEEP) /* I2S1_BCLK -- PCH_WP */
PAD_CFG_GPO(GPIO_76, 0, DEEP) /* I2S1_WS_SYNC -- SPK_PA_EN */
PAD_CFG_GPI(GPIO_77, UP_20K, DEEP) /* I2S1_SDI */
PAD_CFG_GPO(GPIO_78, 1, DEEP) /* I2S1_SDO -- EN_PP3300_DX_LTE_SOC */
/* DMIC or I2S4 */
/* AVS_DMIC_CLK_A1 */
PAD_CFG_NF_IOSSTATE(GPIO_79, NATIVE, DEEP, NF1, IGNORE)
PAD_CFG_NF(GPIO_80, NATIVE, DEEP, NF1) /* AVS_DMIC_CLK_B1 */
PAD_CFG_NF(GPIO_81, NATIVE, DEEP, NF1) /* AVS_DMIC_DATA_1 */
PAD_CFG_GPI(GPIO_82, DN_20K, DEEP) /* unused -- strap */
PAD_CFG_NF(GPIO_83, NATIVE, DEEP, NF1) /* AVS_DMIC_DATA_2 */
/* I2S2 -- Headset amp */
PAD_CFG_NF(GPIO_84, NATIVE, DEEP, NF1) /* AVS_I2S2_MCLK */
PAD_CFG_NF(GPIO_85, NATIVE, DEEP, NF1) /* AVS_I2S2_BCLK */
PAD_CFG_NF(GPIO_86, NATIVE, DEEP, NF1) /* AVS_I2S2_SW_SYNC */
PAD_CFG_NF(GPIO_87, NATIVE, DEEP, NF1) /* AVS_I2S2_SDI */
PAD_CFG_NF(GPIO_88, NATIVE, DEEP, NF1) /* AVS_I2S2_SDO */
/* I2S3 -- largely unused */
PAD_CFG_GPI(GPIO_89, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_90, UP_20K, DEEP) /* GPS_HOST_WAKE */
PAD_CFG_GPO(GPIO_91, 1, DEEP) /* GPS_EN */
PAD_CFG_GPI(GPIO_92, DN_20K, DEEP) /* unused -- strap */
/* Fast SPI */
PAD_CFG_NF_IOSSTATE(GPIO_97, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CS0_B */
PAD_CFG_GPI(GPIO_98, UP_20K, DEEP) /* FST_SPI_CS1_B -- unused */
PAD_CFG_NF_IOSSTATE(GPIO_99, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_MOSI_IO0 */
PAD_CFG_NF_IOSSTATE(GPIO_100, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_MISO_IO1 */
PAD_CFG_GPI(GPIO_101, NONE, DEEP) /* FST_IO2 -- MEM_CONFIG0 */
PAD_CFG_GPI(GPIO_102, NONE, DEEP) /* FST_IO3 -- MEM_CONFIG1 */
PAD_CFG_NF_IOSSTATE(GPIO_103, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CLK */
PAD_CFG_NF_IOSSTATE(FST_SPI_CLK_FB, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CLK_FB */
PAD_CFG_NF_IOSSTATE(GPIO_106, NATIVE, DEEP, NF3, IGNORE) /* FST_SPI_CS2_N */
/* SIO_SPI_0 - Used for FP */
PAD_CFG_NF(GPIO_104, NATIVE, DEEP, NF1) /* SIO_SPI_0_CLK */
PAD_CFG_NF(GPIO_105, NATIVE, DEEP, NF1) /* SIO_SPI_0_FS0 */
PAD_CFG_NF(GPIO_109, NATIVE, DEEP, NF1) /* SIO_SPI_0_RXD */
PAD_CFG_NF(GPIO_110, NATIVE, DEEP, NF1) /* SIO_SPI_0_TXD */
/* SIO_SPI_1 -- largely unused */
PAD_CFG_GPI(GPIO_111, UP_20K, DEEP) /* SIO_SPI_1_CLK */
PAD_CFG_GPI(GPIO_112, UP_20K, DEEP) /* SIO_SPI_1_FS0 */
PAD_CFG_GPI(GPIO_113, UP_20K, DEEP) /* SIO_SPI_1_FS1 */
/* Headset interrupt */
PAD_CFG_GPI_APIC_LOW(GPIO_116, NONE, DEEP) /* SIO_SPI_1_RXD */
PAD_CFG_GPI(GPIO_117, UP_20K, DEEP) /* SIO_SPI_1_TXD */
/* SIO_SPI_2 -- unused */
PAD_CFG_GPI(GPIO_118, UP_20K, DEEP) /* SIO_SPI_2_CLK */
PAD_CFG_GPI(GPIO_119, UP_20K, DEEP) /* SIO_SPI_2_FS0 */
PAD_CFG_GPI(GPIO_120, UP_20K, DEEP) /* SIO_SPI_2_FS1 */
PAD_CFG_GPI(GPIO_121, UP_20K, DEEP) /* SIO_SPI_2_FS2 */
/* WLAN_PE_RST - default to deasserted */
PAD_CFG_GPO(GPIO_122, 0, DEEP) /* SIO_SPI_2_RXD */
PAD_CFG_GPI(GPIO_123, UP_20K, DEEP) /* SIO_SPI_2_TXD */
/* Debug tracing */
PAD_CFG_GPI(GPIO_0, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_1, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_2, UP_20K, DEEP)
PAD_CFG_GPI_SCI_HIGH(GPIO_3, DN_20K, DEEP, LEVEL) /* FP_INT */
PAD_CFG_GPI(GPIO_4, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_5, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_6, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_7, UP_20K, DEEP)
PAD_CFG_GPI(GPIO_8, UP_20K, DEEP)
PAD_CFG_GPI_APIC_LOW(GPIO_9, NONE, DEEP) /* dTPM IRQ */
PAD_CFG_GPI(GPIO_10, DN_20K, DEEP) /* Board phase enforcement */
PAD_CFG_GPI_SCI_LOW(GPIO_11, NONE, DEEP, EDGE_SINGLE) /* EC SCI */
PAD_CFG_GPI(GPIO_12, UP_20K, DEEP) /* unused */
PAD_CFG_GPI_APIC_LOW(GPIO_13, NONE, DEEP) /* PEN_INT_ODL */
PAD_CFG_GPI_APIC_HIGH(GPIO_14, DN_20K, DEEP) /* FP_INT */
PAD_CFG_GPI_SCI_LOW(GPIO_15, NONE, DEEP, EDGE_SINGLE) /* TRACKPAD_INT_1V8_ODL */
PAD_CFG_GPI(GPIO_16, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_17, UP_20K, DEEP) /* 1 vs 4 DMIC config */
PAD_CFG_GPI_APIC_LOW(GPIO_18, NONE, DEEP) /* Trackpad IRQ */
PAD_CFG_GPI(GPIO_19, UP_20K, DEEP) /* unused */
PAD_CFG_GPI_APIC_LOW(GPIO_20, UP_20K, DEEP) /* NFC IRQ */
PAD_CFG_GPI_APIC_LOW(GPIO_21, NONE, DEEP) /* Touch IRQ */
PAD_CFG_GPI_SCI_LOW(GPIO_22, NONE, DEEP, EDGE_SINGLE) /* EC wake */
PAD_CFG_GPI(GPIO_23, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_24, NONE, DEEP) /* PEN_PDCT_ODL */
PAD_CFG_GPI(GPIO_25, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_26, UP_20K, DEEP) /* unused */
PAD_CFG_GPI(GPIO_27, UP_20K, DEEP) /* unused */
PAD_CFG_GPI_APIC_LOW(GPIO_28, NONE, DEEP) /* TPM IRQ */
PAD_CFG_GPO(GPIO_29, 1, DEEP) /* FP reset */
PAD_CFG_GPI_APIC_LOW(GPIO_30, NONE, DEEP) /* KB IRQ */
PAD_CFG_GPO(GPIO_31, 0, DEEP) /* NFC FW DL */
PAD_CFG_NF(GPIO_32, NONE, DEEP, NF5) /* SUS_CLK2 */
PAD_CFG_GPI_APIC_LOW(GPIO_33, NONE, DEEP) /* PMIC IRQ */
PAD_CFG_GPI(GPIO_34, UP_20K, DEEP) /* unused */
PAD_CFG_GPO(GPIO_35, 0, DEEP) /* PEN_RESET - active high */
PAD_CFG_GPO(GPIO_36, 0, DEEP) /* touch reset */
PAD_CFG_GPI(GPIO_37, UP_20K, DEEP) /* unused */
/* LPSS_UART[0:2] */
PAD_CFG_GPI(GPIO_38, NONE, DEEP) /* LPSS_UART0_RXD - MEM_CONFIG2*/
/* Next 2 are straps */
PAD_CFG_GPI(GPIO_39, DN_20K, DEEP) /* LPSS_UART0_TXD - unused */
PAD_CFG_GPI(GPIO_40, DN_20K, DEEP) /* LPSS_UART0_RTS - unused */
PAD_CFG_GPI(GPIO_41, NONE, DEEP) /* LPSS_UART0_CTS - EC_IN_RW */
PAD_CFG_NF(GPIO_42, NATIVE, DEEP, NF1) /* LPSS_UART1_RXD */
PAD_CFG_NF(GPIO_43, NATIVE, DEEP, NF1) /* LPSS_UART1_TXD */
PAD_CFG_GPO(GPIO_44, 1, DEEP) /* GPS_RST_ODL */
PAD_CFG_GPI(GPIO_45, NONE, DEEP) /* LPSS_UART1_CTS - MEM_CONFIG3 */
PAD_CFG_NF(GPIO_46, NATIVE, DEEP, NF1) /* LPSS_UART2_RXD */
PAD_CFG_NF_IOSSTATE(GPIO_47, NATIVE, DEEP, NF1, TX1_RX_DCR_X0) /* UART2 TX */
PAD_CFG_GPI(GPIO_48, UP_20K, DEEP) /* LPSS_UART2_RTS - unused */
PAD_CFG_GPI_SMI_LOW(GPIO_49, NONE, DEEP, EDGE_SINGLE) /* LPSS_UART2_CTS - EC_SMI_L */
/* Camera interface -- completely unused */
PAD_CFG_GPI(GPIO_62, UP_20K, DEEP) /* GP_CAMERASB00 */
PAD_CFG_GPI(GPIO_63, UP_20K, DEEP) /* GP_CAMERASB01 */
PAD_CFG_GPI(GPIO_64, UP_20K, DEEP) /* GP_CAMERASB02 */
PAD_CFG_GPI(GPIO_65, UP_20K, DEEP) /* GP_CAMERASB03 */
PAD_CFG_GPI(GPIO_66, UP_20K, DEEP) /* GP_CAMERASB04 */
PAD_CFG_GPI(GPIO_67, UP_20K, DEEP) /* GP_CAMERASB05 */
PAD_CFG_GPI(GPIO_68, UP_20K, DEEP) /* GP_CAMERASB06 */
PAD_CFG_GPI(GPIO_69, UP_20K, DEEP) /* GP_CAMERASB07 */
PAD_CFG_GPI(GPIO_70, UP_20K, DEEP) /* GP_CAMERASB08 */
PAD_CFG_GPI(GPIO_71, UP_20K, DEEP) /* GP_CAMERASB09 */
PAD_CFG_GPI(GPIO_72, UP_20K, DEEP) /* GP_CAMERASB10 */
PAD_CFG_GPI(GPIO_73, UP_20K, DEEP) /* GP_CAMERASB11 */
>;
};

View File

@ -37,62 +37,110 @@
};
#endif
#ifdef CONFIG_TPL
#ifdef CONFIG_HAVE_MICROCODE
u-boot-tpl-with-ucode-ptr {
offset = <CONFIG_TPL_TEXT_BASE>;
};
u-boot-tpl-dtb {
};
u-boot-spl {
offset = <CONFIG_SPL_TEXT_BASE>;
};
u-boot-spl-dtb {
#endif
spl {
type = "section";
offset = <CONFIG_X86_OFFSET_SPL>;
u-boot-spl {
};
u-boot-spl-dtb {
};
};
u-boot {
offset = <CONFIG_SYS_TEXT_BASE>;
type = "section";
offset = <CONFIG_X86_OFFSET_U_BOOT>;
u-boot-nodtb {
};
u-boot-dtb {
};
};
#elif defined(CONFIG_SPL)
u-boot-spl-with-ucode-ptr {
offset = <CONFIG_SPL_TEXT_BASE>;
offset = <CONFIG_X86_OFFSET_SPL>;
};
u-boot-dtb-with-ucode2 {
type = "u-boot-dtb-with-ucode";
};
u-boot {
/*
* TODO(sjg@chromium.org):
* Normally we use CONFIG_SYS_TEXT_BASE as the flash offset. But
* for boards with textbase in SDRAM we cannot do this. Just use
* an assumed-valid value (1MB before the end of flash) here so
* that we can actually build an image for coreboot, etc.
* We need a better solution, perhaps a separate Kconfig.
*/
#if CONFIG_SYS_TEXT_BASE == 0x1110000
offset = <0xfff00000>;
#else
offset = <CONFIG_SYS_TEXT_BASE>;
#endif
offset = <CONFIG_X86_OFFSET_U_BOOT>;
};
#else
# ifdef CONFIG_SPL
u-boot {
offset = <CONFIG_SYS_TEXT_BASE>;
};
# else
/* If there is no SPL then we need to put microcode in U-Boot */
u-boot-with-ucode-ptr {
offset = <CONFIG_SYS_TEXT_BASE>;
offset = <CONFIG_X86_OFFSET_U_BOOT>;
};
# endif
#endif
#ifdef CONFIG_HAVE_MICROCODE
u-boot-dtb-with-ucode {
};
u-boot-ucode {
align = <16>;
};
#else
u-boot-dtb {
};
#endif
#ifdef CONFIG_HAVE_X86_FIT
intel-fit {
};
intel-fit-ptr {
};
#endif
#ifdef CONFIG_HAVE_MRC
intel-mrc {
offset = <CONFIG_X86_MRC_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_FSP
#ifdef CONFIG_FSP_VERSION1
intel-fsp {
filename = CONFIG_FSP_FILE;
offset = <CONFIG_FSP_ADDR>;
};
#endif
#ifdef CONFIG_FSP_VERSION2
intel-descriptor {
filename = CONFIG_FLASH_DESCRIPTOR_FILE;
};
intel-ifwi {
filename = CONFIG_IFWI_INPUT_FILE;
convert-fit;
section {
size = <0x8000>;
ifwi-replace;
ifwi-subpart = "IBBP";
ifwi-entry = "IBBL";
u-boot-tpl {
};
x86-start16-tpl {
offset = <0x7800>;
};
x86-reset16-tpl {
offset = <0x7ff0>;
};
};
};
intel-fsp-m {
filename = CONFIG_FSP_FILE_M;
};
intel-fsp-s {
filename = CONFIG_FSP_FILE_S;
};
#endif
fdtmap {
};
#ifdef CONFIG_HAVE_CMC
intel-cmc {
filename = CONFIG_CMC_FILE;
@ -138,5 +186,8 @@
offset = <CONFIG_RESET_VEC_LOC>;
};
#endif
image-header {
location = "end";
};
};
#endif

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2019 Google LLC
*/
#ifndef _ASM_ARCH_CPU_H
#define _ASM_ARCH_CPU_H
/* Common Timer Copy (CTC) frequency - 19.2MHz */
#define CTC_FREQ 19200000
#define MAX_PCIE_PORTS 6
#define CLKREQ_DISABLED 0xf
#ifndef __ASSEMBLY__
/* Flush L1D to L2 */
void cpu_flush_l1d_to_l2(void);
#endif
#endif /* _ASM_ARCH_CPU_H */

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright 2019 Google LLC
*/
#ifndef __FSP_CONFIGS_H__
#define __FSP_CONFIGS_H__
#define FSPT_UPD_SIGNATURE 0x545F4450554C5041 /* 'APLUPD_T' */
#define FSPM_UPD_SIGNATURE 0x4D5F4450554C5041 /* 'APLUPD_M' */
#define FSPS_UPD_SIGNATURE 0x535F4450554C5041 /* 'APLUPD_S' */
#define VBT_SIGNATURE 0x54425624
#endif

View File

@ -0,0 +1,123 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright (c) 2019, Intel Corporation. All rights reserved.
* Copyright 2019 Google LLC
*/
#ifndef __ASM_ARCH_FSP_M_UDP_H
#define __ASM_ARCH_FSP_M_UDP_H
#include <asm/fsp2/fsp_api.h>
#define FSP_DRAM_CHANNELS 4
struct __packed fspm_arch_upd {
u8 revision;
u8 reserved[3];
void *nvs_buffer_ptr;
void *stack_base;
u32 stack_size;
u32 boot_loader_tolum_size;
u32 boot_mode;
u8 reserved1[8];
};
struct __packed fsp_ram_channel {
u8 rank_enable;
u8 device_width;
u8 dram_density;
u8 option;
u8 odt_config;
u8 tristate_clk1;
u8 mode2_n;
u8 odt_levels;
};
struct __packed fsp_m_config {
u32 serial_debug_port_address;
u8 serial_debug_port_type;
u8 serial_debug_port_device;
u8 serial_debug_port_stride_size;
u8 mrc_fast_boot;
u8 igd;
u8 igd_dvmt50_pre_alloc;
u8 igd_aperture_size;
u8 gtt_size;
u8 primary_video_adaptor;
u8 package;
u8 profile;
u8 memory_down;
u8 ddr3_l_page_size;
u8 ddr3_lasr;
u8 scrambler_support;
u8 interleaved_mode;
u16 channel_hash_mask;
u16 slice_hash_mask;
u8 channels_slices_enable;
u8 min_ref_rate2x_enable;
u8 dual_rank_support_enable;
u8 rmt_mode;
u16 memory_size_limit;
u16 low_memory_max_value;
u16 high_memory_max_value;
u8 disable_fast_boot;
u8 dimm0_spd_address;
u8 dimm1_spd_address;
struct fsp_ram_channel chan[FSP_DRAM_CHANNELS];
u8 rmt_check_run;
u16 rmt_margin_check_scale_high_threshold;
u8 ch_bit_swizzling[FSP_DRAM_CHANNELS][32];
u32 msg_level_mask;
u8 unused_upd_space0[4];
u8 pre_mem_gpio_table_pin_num[4];
u32 pre_mem_gpio_table_ptr;
u8 pre_mem_gpio_table_entry_num;
u8 enhance_port8xh_decoding;
u8 spd_write_enable;
u8 mrc_data_saving;
u32 oem_loading_base;
u8 oem_file_name[16];
void *mrc_boot_data_ptr;
u8 e_mmc_trace_len;
u8 skip_cse_rbp;
u8 npk_en;
u8 fw_trace_en;
u8 fw_trace_destination;
u8 recover_dump;
u8 msc0_wrap;
u8 msc1_wrap;
u32 msc0_size;
u32 msc1_size;
u8 pti_mode;
u8 pti_training;
u8 pti_speed;
u8 punit_mlvl;
u8 pmc_mlvl;
u8 sw_trace_en;
u8 periodic_retraining_disable;
u8 enable_reset_system;
u8 enable_s3_heci2;
u8 unused_upd_space1[3];
void *variable_nvs_buffer_ptr;
u8 reserved_fspm_upd[12];
};
/** FSP-M UPD Configuration */
struct __packed fspm_upd {
struct fsp_upd_header header;
struct fspm_arch_upd arch;
struct fsp_m_config config;
u8 unused_upd_space2[158];
u16 upd_terminator;
};
#endif

View File

@ -0,0 +1,292 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright (c) 2016, Intel Corporation. All rights reserved.
* Copyright 2019 Google LLC
*/
#ifndef __ASM_ARCH_FSP_S_UDP_H
#define __ASM_ARCH_FSP_S_UDP_H
#include <asm/fsp2/fsp_api.h>
struct __packed fsp_s_config {
u8 active_processor_cores;
u8 disable_core1;
u8 disable_core2;
u8 disable_core3;
u8 vmx_enable;
u8 proc_trace_mem_size;
u8 proc_trace_enable;
u8 eist;
u8 boot_p_state;
u8 enable_cx;
u8 c1e;
u8 bi_proc_hot;
u8 pkg_c_state_limit;
u8 c_state_auto_demotion;
u8 c_state_un_demotion;
u8 max_core_c_state;
u8 pkg_c_state_demotion;
u8 pkg_c_state_un_demotion;
u8 turbo_mode;
u8 hda_verb_table_entry_num;
u32 hda_verb_table_ptr;
u8 p2sb_unhide;
u8 ipu_en;
u8 ipu_acpi_mode;
u8 force_wake;
u32 gtt_mm_adr;
u32 gm_adr;
u8 pavp_lock;
u8 graphics_freq_modify;
u8 graphics_freq_req;
u8 graphics_video_freq;
u8 pm_lock;
u8 dop_clock_gating;
u8 unsolicited_attack_override;
u8 wopcm_support;
u8 wopcm_size;
u8 power_gating;
u8 unit_level_clock_gating;
u8 fast_boot;
u8 dyn_sr;
u8 sa_ipu_enable;
u8 pm_support;
u8 enable_render_standby;
u32 logo_size;
u32 logo_ptr;
u32 graphics_config_ptr;
u8 pavp_enable;
u8 pavp_pr3;
u8 cd_clock;
u8 pei_graphics_peim_init;
u8 write_protection_enable[5];
u8 read_protection_enable[5];
u16 protected_range_limit[5];
u16 protected_range_base[5];
u8 gmm;
u8 clk_gating_pgcb_clk_trunk;
u8 clk_gating_sb;
u8 clk_gating_sb_clk_trunk;
u8 clk_gating_sb_clk_partition;
u8 clk_gating_core;
u8 clk_gating_dma;
u8 clk_gating_reg_access;
u8 clk_gating_host;
u8 clk_gating_partition;
u8 clk_gating_trunk;
u8 hda_enable;
u8 dsp_enable;
u8 pme;
u8 hd_audio_io_buffer_ownership;
u8 hd_audio_io_buffer_voltage;
u8 hd_audio_vc_type;
u8 hd_audio_link_frequency;
u8 hd_audio_i_disp_link_frequency;
u8 hd_audio_i_disp_link_tmode;
u8 dsp_endpoint_dmic;
u8 dsp_endpoint_bluetooth;
u8 dsp_endpoint_i2s_skp;
u8 dsp_endpoint_i2s_hp;
u8 audio_ctl_pwr_gate;
u8 audio_dsp_pwr_gate;
u8 mmt;
u8 hmt;
u8 hd_audio_pwr_gate;
u8 hd_audio_clk_gate;
u32 dsp_feature_mask;
u32 dsp_pp_module_mask;
u8 bios_cfg_lock_down;
u8 hpet;
u8 hpet_bdf_valid;
u8 hpet_bus_number;
u8 hpet_device_number;
u8 hpet_function_number;
u8 io_apic_bdf_valid;
u8 io_apic_bus_number;
u8 io_apic_device_number;
u8 io_apic_function_number;
u8 io_apic_entry24_119;
u8 io_apic_id;
u8 io_apic_range_select;
u8 ish_enable;
u8 bios_interface;
u8 bios_lock;
u8 spi_eiss;
u8 bios_lock_sw_smi_number;
u8 lpss_s0ix_enable;
u8 unused_upd_space0[1];
u8 i2c_clk_gate_cfg[8];
u8 hsuart_clk_gate_cfg[4];
u8 spi_clk_gate_cfg[3];
u8 i2c0_enable;
u8 i2c1_enable;
u8 i2c2_enable;
u8 i2c3_enable;
u8 i2c4_enable;
u8 i2c5_enable;
u8 i2c6_enable;
u8 i2c7_enable;
u8 hsuart0_enable;
u8 hsuart1_enable;
u8 hsuart2_enable;
u8 hsuart3_enable;
u8 spi0_enable;
u8 spi1_enable;
u8 spi2_enable;
u8 os_dbg_enable;
u8 dci_en;
u32 uart2_kernel_debug_base_address;
u8 pcie_clock_gating_disabled;
u8 pcie_root_port8xh_decode;
u8 pcie8xh_decode_port_index;
u8 pcie_root_port_peer_memory_write_enable;
u8 pcie_aspm_sw_smi_number;
u8 unused_upd_space1[1];
u8 pcie_root_port_en[6];
u8 pcie_rp_hide[6];
u8 pcie_rp_slot_implemented[6];
u8 pcie_rp_hot_plug[6];
u8 pcie_rp_pm_sci[6];
u8 pcie_rp_ext_sync[6];
u8 pcie_rp_transmitter_half_swing[6];
u8 pcie_rp_acs_enabled[6];
u8 pcie_rp_clk_req_supported[6];
u8 pcie_rp_clk_req_number[6];
u8 pcie_rp_clk_req_detect[6];
u8 advanced_error_reporting[6];
u8 pme_interrupt[6];
u8 unsupported_request_report[6];
u8 fatal_error_report[6];
u8 no_fatal_error_report[6];
u8 correctable_error_report[6];
u8 system_error_on_fatal_error[6];
u8 system_error_on_non_fatal_error[6];
u8 system_error_on_correctable_error[6];
u8 pcie_rp_speed[6];
u8 physical_slot_number[6];
u8 pcie_rp_completion_timeout[6];
u8 ptm_enable[6];
u8 pcie_rp_aspm[6];
u8 pcie_rp_l1_substates[6];
u8 pcie_rp_ltr_enable[6];
u8 pcie_rp_ltr_config_lock[6];
u8 pme_b0_s5_dis;
u8 pci_clock_run;
u8 timer8254_clk_setting;
u8 enable_sata;
u8 sata_mode;
u8 sata_salp_support;
u8 sata_pwr_opt_enable;
u8 e_sata_speed_limit;
u8 speed_limit;
u8 unused_upd_space2[1];
u8 sata_ports_enable[2];
u8 sata_ports_dev_slp[2];
u8 sata_ports_hot_plug[2];
u8 sata_ports_interlock_sw[2];
u8 sata_ports_external[2];
u8 sata_ports_spin_up[2];
u8 sata_ports_solid_state_drive[2];
u8 sata_ports_enable_dito_config[2];
u8 sata_ports_dm_val[2];
u8 unused_upd_space3[2];
u16 sata_ports_dito_val[2];
u16 sub_system_vendor_id;
u16 sub_system_id;
u8 crid_settings;
u8 reset_select;
u8 sdcard_enabled;
u8 e_mmc_enabled;
u8 e_mmc_host_max_speed;
u8 ufs_enabled;
u8 sdio_enabled;
u8 gpp_lock;
u8 sirq_enable;
u8 sirq_mode;
u8 start_frame_pulse;
u8 smbus_enable;
u8 arp_enable;
u8 unused_upd_space4;
u16 num_rsvd_smbus_addresses;
u8 rsvd_smbus_address_table[128];
u8 disable_compliance_mode;
u8 usb_per_port_ctl;
u8 usb30_mode;
u8 unused_upd_space5[1];
u8 port_usb20_enable[8];
u8 port_us20b_over_current_pin[8];
u8 usb_otg;
u8 hsic_support_enable;
u8 port_usb30_enable[6];
u8 port_us30b_over_current_pin[6];
u8 ssic_port_enable[2];
u16 dlane_pwr_gating;
u8 vtd_enable;
u8 lock_down_global_smi;
u16 reset_wait_timer;
u8 rtc_lock;
u8 sata_test_mode;
u8 ssic_rate[2];
u16 dynamic_power_gating;
u16 pcie_rp_ltr_max_snoop_latency[6];
u8 pcie_rp_snoop_latency_override_mode[6];
u8 unused_upd_space6[2];
u16 pcie_rp_snoop_latency_override_value[6];
u8 pcie_rp_snoop_latency_override_multiplier[6];
u8 skip_mp_init;
u8 dci_auto_detect;
u16 pcie_rp_ltr_max_non_snoop_latency[6];
u8 pcie_rp_non_snoop_latency_override_mode[6];
u8 tco_timer_halt_lock;
u8 pwr_btn_override_period;
u16 pcie_rp_non_snoop_latency_override_value[6];
u8 pcie_rp_non_snoop_latency_override_multiplier[6];
u8 pcie_rp_slot_power_limit_scale[6];
u8 pcie_rp_slot_power_limit_value[6];
u8 disable_native_power_button;
u8 power_butter_debounce_mode;
u32 sdio_tx_cmd_cntl;
u32 sdio_tx_data_cntl1;
u32 sdio_tx_data_cntl2;
u32 sdio_rx_cmd_data_cntl1;
u32 sdio_rx_cmd_data_cntl2;
u32 sdcard_tx_cmd_cntl;
u32 sdcard_tx_data_cntl1;
u32 sdcard_tx_data_cntl2;
u32 sdcard_rx_cmd_data_cntl1;
u32 sdcard_rx_strobe_cntl;
u32 sdcard_rx_cmd_data_cntl2;
u32 emmc_tx_cmd_cntl;
u32 emmc_tx_data_cntl1;
u32 emmc_tx_data_cntl2;
u32 emmc_rx_cmd_data_cntl1;
u32 emmc_rx_strobe_cntl;
u32 emmc_rx_cmd_data_cntl2;
u32 emmc_master_sw_cntl;
u8 pcie_rp_selectable_deemphasis[6];
u8 monitor_mwait_enable;
u8 hd_audio_dsp_uaa_compliance;
u32 ipc[4];
u8 sata_ports_disable_dynamic_pg[2];
u8 init_s3_cpu;
u8 skip_punit_init;
u8 unused_upd_space7[4];
u8 port_usb20_per_port_tx_pe_half[8];
u8 port_usb20_per_port_pe_txi_set[8];
u8 port_usb20_per_port_txi_set[8];
u8 port_usb20_hs_skew_sel[8];
u8 port_usb20_i_usb_tx_emphasis_en[8];
u8 port_usb20_per_port_rxi_set[8];
u8 port_usb20_hs_npre_drv_sel[8];
u8 reserved_fsps_upd[16];
};
/** struct fsps_upd - FSP-S Configuration */
struct __packed fsps_upd {
struct fsp_upd_header header;
struct fsp_s_config config;
u8 unused_upd_space2[46];
u16 upd_terminator;
};
#endif

View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright 2019 Google LLC
*/
#ifndef __FSP_VPD_H
#define __FSP_VPD_H
/* Nothing to declare here for FSP2 */
#endif

View File

@ -0,0 +1,485 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Definitions for the GPIO subsystem on Apollolake
*
* Copyright (C) 2015 - 2017 Intel Corp.
* (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
*
* Placed in a separate file since some of these definitions can be used from
* assembly code
*
* Taken from gpio_apl.h in coreboot
*/
#ifndef _ASM_ARCH_GPIO_H_
#define _ASM_ARCH_GPIO_H_
/* Port ids */
#define PID_GPIO_SW 0xC0
#define PID_GPIO_S 0xC2
#define PID_GPIO_W 0xC7
#define PID_GPIO_NW 0xC4
#define PID_GPIO_N 0xC5
#define PID_ITSS 0xD0
#define PID_RTC 0xD1
/*
* Miscellaneous Configuration register(MISCCFG). These are community-specific
* registers and are meant to house miscellaneous configuration fields per
* community. There are 8 GPIO groups: GPP_0 -> GPP_8 (Group 3 is absent)
*/
#define GPIO_MISCCFG 0x10 /* Miscellaneous Configuration offset */
#define GPIO_GPE_SW_31_0 0 /* SOUTHWEST GPIO# 0 ~ 31 belong to GROUP0 */
#define GPIO_GPE_SW_63_32 1 /* SOUTHWEST GPIO# 32 ~ 42 belong to GROUP1 */
#define GPIO_GPE_W_31_0 2 /* WEST GPIO# 0 ~ 25 belong to GROUP2 */
#define GPIO_GPE_NW_31_0 4 /* NORTHWEST GPIO# 0 ~ 17 belong to GROUP4 */
#define GPIO_GPE_NW_63_32 5 /* NORTHWEST GPIO# 32 ~ 63 belong to GROUP5 */
#define GPIO_GPE_NW_95_64 6 /* NORTHWEST GPIO# 64 ~ 76 belong to GROUP6 */
#define GPIO_GPE_N_31_0 7 /* NORTH GPIO# 0 ~ 31 belong to GROUP7 */
#define GPIO_GPE_N_63_32 8 /* NORTH GPIO# 32 ~ 61 belong to GROUP8 */
#define GPIO_MAX_NUM_PER_GROUP 32
/*
* Host Software Pad Ownership Register.
* The pins in the community are divided into 3 groups:
* GPIO 0 ~ 31, GPIO 32 ~ 63, GPIO 64 ~ 95
*/
#define HOSTSW_OWN_REG_0 0x80
#define PAD_CFG_BASE 0x500
#define GPI_INT_STS_0 0x100
#define GPI_INT_EN_0 0x110
#define GPI_SMI_STS_0 0x140
#define GPI_SMI_EN_0 0x150
#define NUM_N_PADS (PAD_N(SVID0_CLK) + 1)
#define NUM_NW_PADS (PAD_NW(GPIO_123) + 1)
#define NUM_W_PADS (PAD_W(SUSPWRDNACK) + 1)
#define NUM_SW_PADS (PAD_SW(LPC_FRAMEB) + 1)
#define NUM_N_GPI_REGS \
(ALIGN(NUM_N_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
#define NUM_NW_GPI_REGS \
(ALIGN(NUM_NW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
#define NUM_W_GPI_REGS \
(ALIGN(NUM_W_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
#define NUM_SW_GPI_REGS \
(ALIGN(NUM_SW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
/*
* Total number of GPI status registers across all GPIO communities in the SOC
*/
#define NUM_GPI_STATUS_REGS (NUM_N_GPI_REGS + NUM_NW_GPI_REGS \
+ NUM_W_GPI_REGS + NUM_SW_GPI_REGS)
/* North community pads */
#define GPIO_0 0
#define GPIO_1 1
#define GPIO_2 2
#define GPIO_3 3
#define GPIO_4 4
#define GPIO_5 5
#define GPIO_6 6
#define GPIO_7 7
#define GPIO_8 8
#define GPIO_9 9
#define GPIO_10 10
#define GPIO_11 11
#define GPIO_12 12
#define GPIO_13 13
#define GPIO_14 14
#define GPIO_15 15
#define GPIO_16 16
#define GPIO_17 17
#define GPIO_18 18
#define GPIO_19 19
#define GPIO_20 20
#define GPIO_21 21
#define GPIO_22 22
#define GPIO_23 23
#define GPIO_24 24
#define GPIO_25 25
#define GPIO_26 26
#define GPIO_27 27
#define GPIO_28 28
#define GPIO_29 29
#define GPIO_30 30
#define GPIO_31 31
#define GPIO_32 32
#define GPIO_33 33
#define GPIO_34 34
#define GPIO_35 35
#define GPIO_36 36
#define GPIO_37 37
#define GPIO_38 38
#define GPIO_39 39
#define GPIO_40 40
#define GPIO_41 41
#define GPIO_42 42
#define GPIO_43 43
#define GPIO_44 44
#define GPIO_45 45
#define GPIO_46 46
#define GPIO_47 47
#define GPIO_48 48
#define GPIO_49 49
#define GPIO_62 50
#define GPIO_63 51
#define GPIO_64 52
#define GPIO_65 53
#define GPIO_66 54
#define GPIO_67 55
#define GPIO_68 56
#define GPIO_69 57
#define GPIO_70 58
#define GPIO_71 59
#define GPIO_72 60
#define GPIO_73 61
#define JTAG_TCK 62
#define JTAG_TRST_B 63
#define JTAG_TMS 64
#define JTAG_TDI 65
#define JTAG_CX_PMODE 66
#define JTAG_CX_PREQ_B 67
#define JTAGX 68
#define JTAG_CX_PRDY_B 69
#define JTAG_TDO 70
#define CNV_BRI_DT 71
#define CNV_BRI_RSP 72
#define CNV_RGI_DT 73
#define CNV_RGI_RSP 74
#define SVID0_ALERT_B 75
#define SVID0_DATA 76
#define SVID0_CLK 77
/* Northwest community pads */
#define GPIO_187 78
#define GPIO_188 79
#define GPIO_189 80
#define GPIO_190 81
#define GPIO_191 82
#define GPIO_192 83
#define GPIO_193 84
#define GPIO_194 85
#define GPIO_195 86
#define GPIO_196 87
#define GPIO_197 88
#define GPIO_198 89
#define GPIO_199 90
#define GPIO_200 91
#define GPIO_201 92
#define GPIO_202 93
#define GPIO_203 94
#define GPIO_204 95
#define PMC_SPI_FS0 96
#define PMC_SPI_FS1 97
#define PMC_SPI_FS2 98
#define PMC_SPI_RXD 99
#define PMC_SPI_TXD 100
#define PMC_SPI_CLK 101
#define PMIC_PWRGOOD 102
#define PMIC_RESET_B 103
#define GPIO_213 104
#define GPIO_214 105
#define GPIO_215 106
#define PMIC_THERMTRIP_B 107
#define PMIC_STDBY 108
#define PROCHOT_B 109
#define PMIC_I2C_SCL 110
#define PMIC_I2C_SDA 111
#define GPIO_74 112
#define GPIO_75 113
#define GPIO_76 114
#define GPIO_77 115
#define GPIO_78 116
#define GPIO_79 117
#define GPIO_80 118
#define GPIO_81 119
#define GPIO_82 120
#define GPIO_83 121
#define GPIO_84 122
#define GPIO_85 123
#define GPIO_86 124
#define GPIO_87 125
#define GPIO_88 126
#define GPIO_89 127
#define GPIO_90 128
#define GPIO_91 129
#define GPIO_92 130
#define GPIO_97 131
#define GPIO_98 132
#define GPIO_99 133
#define GPIO_100 134
#define GPIO_101 135
#define GPIO_102 136
#define GPIO_103 137
#define FST_SPI_CLK_FB 138
#define GPIO_104 139
#define GPIO_105 140
#define GPIO_106 141
#define GPIO_109 142
#define GPIO_110 143
#define GPIO_111 144
#define GPIO_112 145
#define GPIO_113 146
#define GPIO_116 147
#define GPIO_117 148
#define GPIO_118 149
#define GPIO_119 150
#define GPIO_120 151
#define GPIO_121 152
#define GPIO_122 153
#define GPIO_123 154
/* West community pads */
#define GPIO_124 155
#define GPIO_125 156
#define GPIO_126 157
#define GPIO_127 158
#define GPIO_128 159
#define GPIO_129 160
#define GPIO_130 161
#define GPIO_131 162
#define GPIO_132 163
#define GPIO_133 164
#define GPIO_134 165
#define GPIO_135 166
#define GPIO_136 167
#define GPIO_137 168
#define GPIO_138 169
#define GPIO_139 170
#define GPIO_146 171
#define GPIO_147 172
#define GPIO_148 173
#define GPIO_149 174
#define GPIO_150 175
#define GPIO_151 176
#define GPIO_152 177
#define GPIO_153 178
#define GPIO_154 179
#define GPIO_155 180
#define GPIO_209 181
#define GPIO_210 182
#define GPIO_211 183
#define GPIO_212 184
#define OSC_CLK_OUT_0 185
#define OSC_CLK_OUT_1 186
#define OSC_CLK_OUT_2 187
#define OSC_CLK_OUT_3 188
#define OSC_CLK_OUT_4 189
#define PMU_AC_PRESENT 190
#define PMU_BATLOW_B 191
#define PMU_PLTRST_B 192
#define PMU_PWRBTN_B 193
#define PMU_RESETBUTTON_B 194
#define PMU_SLP_S0_B 195
#define PMU_SLP_S3_B 196
#define PMU_SLP_S4_B 197
#define PMU_SUSCLK 198
#define PMU_WAKE_B 199
#define SUS_STAT_B 200
#define SUSPWRDNACK 201
/* Southwest community pads */
#define GPIO_205 202
#define GPIO_206 203
#define GPIO_207 204
#define GPIO_208 205
#define GPIO_156 206
#define GPIO_157 207
#define GPIO_158 208
#define GPIO_159 209
#define GPIO_160 210
#define GPIO_161 211
#define GPIO_162 212
#define GPIO_163 213
#define GPIO_164 214
#define GPIO_165 215
#define GPIO_166 216
#define GPIO_167 217
#define GPIO_168 218
#define GPIO_169 219
#define GPIO_170 220
#define GPIO_171 221
#define GPIO_172 222
#define GPIO_179 223
#define GPIO_173 224
#define GPIO_174 225
#define GPIO_175 226
#define GPIO_176 227
#define GPIO_177 228
#define GPIO_178 229
#define GPIO_186 230
#define GPIO_182 231
#define GPIO_183 232
#define SMB_ALERTB 233
#define SMB_CLK 234
#define SMB_DATA 235
#define LPC_ILB_SERIRQ 236
#define LPC_CLKOUT0 237
#define LPC_CLKOUT1 238
#define LPC_AD0 239
#define LPC_AD1 240
#define LPC_AD2 241
#define LPC_AD3 242
#define LPC_CLKRUNB 243
#define LPC_FRAMEB 244
/* PERST_0 not defined */
#define GPIO_PRT0_UDEF 0xFF
#define TOTAL_PADS 245
#define N_OFFSET GPIO_0
#define NW_OFFSET GPIO_187
#define W_OFFSET GPIO_124
#define SW_OFFSET GPIO_205
/* Macros for translating a global pad offset to a local offset */
#define PAD_N(pad) (pad - N_OFFSET)
#define PAD_NW(pad) (pad - NW_OFFSET)
#define PAD_W(pad) (pad - W_OFFSET)
#define PAD_SW(pad) (pad - SW_OFFSET)
/* Linux names of the GPIO devices */
#define GPIO_COMM_N_NAME "INT3452:00"
#define GPIO_COMM_NW_NAME "INT3452:01"
#define GPIO_COMM_W_NAME "INT3452:02"
#define GPIO_COMM_SW_NAME "INT3452:03"
/* Following is used in gpio asl */
#define GPIO_COMM_NAME "INT3452"
#define GPIO_COMM_0_DESC \
"General Purpose Input/Output (GPIO) Controller - North"
#define GPIO_COMM_1_DESC \
"General Purpose Input/Output (GPIO) Controller - Northwest"
#define GPIO_COMM_2_DESC \
"General Purpose Input/Output (GPIO) Controller - West"
#define GPIO_COMM_3_DESC \
"General Purpose Input/Output (GPIO) Controller - Southwest"
#define GPIO_COMM0_PID PID_GPIO_N
#define GPIO_COMM1_PID PID_GPIO_NW
#define GPIO_COMM2_PID PID_GPIO_W
#define GPIO_COMM3_PID PID_GPIO_SW
/*
* IOxAPIC IRQs for the GPIOs, overlap is expected as we encourage to use
* shared IRQ instead of direct IRQ, in case of overlapping, we can easily
* program one of the overlap to shared IRQ to avoid the conflict.
*/
/* NorthWest community pads */
#define PMIC_I2C_SDA_IRQ 0x32
#define GPIO_74_IRQ 0x33
#define GPIO_75_IRQ 0x34
#define GPIO_76_IRQ 0x35
#define GPIO_77_IRQ 0x36
#define GPIO_78_IRQ 0x37
#define GPIO_79_IRQ 0x38
#define GPIO_80_IRQ 0x39
#define GPIO_81_IRQ 0x3A
#define GPIO_82_IRQ 0x3B
#define GPIO_83_IRQ 0x3C
#define GPIO_84_IRQ 0x3D
#define GPIO_85_IRQ 0x3E
#define GPIO_86_IRQ 0x3F
#define GPIO_87_IRQ 0x40
#define GPIO_88_IRQ 0x41
#define GPIO_89_IRQ 0x42
#define GPIO_90_IRQ 0x43
#define GPIO_91_IRQ 0x44
#define GPIO_97_IRQ 0x49
#define GPIO_98_IRQ 0x4A
#define GPIO_99_IRQ 0x4B
#define GPIO_100_IRQ 0x4C
#define GPIO_101_IRQ 0x4D
#define GPIO_102_IRQ 0x4E
#define GPIO_103_IRQ 0x4F
#define GPIO_104_IRQ 0x50
#define GPIO_105_IRQ 0x51
#define GPIO_106_IRQ 0x52
#define GPIO_109_IRQ 0x54
#define GPIO_110_IRQ 0x55
#define GPIO_111_IRQ 0x56
#define GPIO_112_IRQ 0x57
#define GPIO_113_IRQ 0x58
#define GPIO_116_IRQ 0x5B
#define GPIO_117_IRQ 0x5C
#define GPIO_118_IRQ 0x5D
#define GPIO_119_IRQ 0x5E
#define GPIO_120_IRQ 0x5F
#define GPIO_121_IRQ 0x60
#define GPIO_122_IRQ 0x61
#define GPIO_123_IRQ 0x62
/* North community pads */
#define GPIO_0_IRQ 0x63
#define GPIO_1_IRQ 0x64
#define GPIO_2_IRQ 0x65
#define GPIO_3_IRQ 0x66
#define GPIO_4_IRQ 0x67
#define GPIO_5_IRQ 0x68
#define GPIO_6_IRQ 0x69
#define GPIO_7_IRQ 0x6A
#define GPIO_8_IRQ 0x6B
#define GPIO_9_IRQ 0x6C
#define GPIO_10_IRQ 0x6D
#define GPIO_11_IRQ 0x6E
#define GPIO_12_IRQ 0x6F
#define GPIO_13_IRQ 0x70
#define GPIO_14_IRQ 0x71
#define GPIO_15_IRQ 0x72
#define GPIO_16_IRQ 0x73
#define GPIO_17_IRQ 0x74
#define GPIO_18_IRQ 0x75
#define GPIO_19_IRQ 0x76
#define GPIO_20_IRQ 0x77
#define GPIO_21_IRQ 0x32
#define GPIO_22_IRQ 0x33
#define GPIO_23_IRQ 0x34
#define GPIO_24_IRQ 0x35
#define GPIO_25_IRQ 0x36
#define GPIO_26_IRQ 0x37
#define GPIO_27_IRQ 0x38
#define GPIO_28_IRQ 0x39
#define GPIO_29_IRQ 0x3A
#define GPIO_30_IRQ 0x3B
#define GPIO_31_IRQ 0x3C
#define GPIO_32_IRQ 0x3D
#define GPIO_33_IRQ 0x3E
#define GPIO_34_IRQ 0x3F
#define GPIO_35_IRQ 0x40
#define GPIO_36_IRQ 0x41
#define GPIO_37_IRQ 0x42
#define GPIO_38_IRQ 0x43
#define GPIO_39_IRQ 0x44
#define GPIO_40_IRQ 0x45
#define GPIO_41_IRQ 0x46
#define GPIO_42_IRQ 0x47
#define GPIO_43_IRQ 0x48
#define GPIO_44_IRQ 0x49
#define GPIO_45_IRQ 0x4A
#define GPIO_46_IRQ 0x4B
#define GPIO_47_IRQ 0x4C
#define GPIO_48_IRQ 0x4D
#define GPIO_49_IRQ 0x4E
#define GPIO_62_IRQ 0x5B
#define GPIO_63_IRQ 0x5C
#define GPIO_64_IRQ 0x5D
#define GPIO_65_IRQ 0x5E
#define GPIO_66_IRQ 0x5F
#define GPIO_67_IRQ 0x60
#define GPIO_68_IRQ 0x61
#define GPIO_69_IRQ 0x62
#define GPIO_70_IRQ 0x63
#define GPIO_71_IRQ 0x64
#define GPIO_72_IRQ 0x65
#define GPIO_73_IRQ 0x66
#endif /* _ASM_ARCH_GPIO_H_ */

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Intel Corporation.
* Take from coreboot project file of the same name
*/
#ifndef _ASM_ARCH_IOMAP_H
#define _ASM_ARCH_IOMAP_H
#define R_ACPI_PM1_TMR 0x8
/* Put p2sb at 0xd0000000 in TPL */
#define IOMAP_P2SB_BAR 0xd0000000
#define IOMAP_SPI_BASE 0xfe010000
#define IOMAP_ACPI_BASE 0x400
#define IOMAP_ACPI_SIZE 0x100
/*
* Use UART2. To use UART1 you need to set '2' to '1', change device tree serial
* node name and 'reg' property, and update CONFIG_DEBUG_UART_BASE.
*/
#define PCH_DEV_UART PCI_BDF(0, 0x18, 2)
#define PCH_DEV_LPC PCI_BDF(0, 0x1f, 0)
#define PCH_DEV_SPI PCI_BDF(0, 0x0d, 2)
#endif

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Intel Corporation.
* Copyright 2019 Google LLC
*
* Modified from coreboot itss.h
*/
#ifndef _ASM_ARCH_ITSS_H
#define _ASM_ARCH_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)
/* Max PXRC registers in ITSS */
#define MAX_PXRC_CONFIG (PCR_ITSS_PIRQH_ROUT - PCR_ITSS_PIRQA_ROUT + 1)
/* PIRQA Routing Control Register */
#define PCR_ITSS_PIRQA_ROUT 0x3100
/* PIRQB Routing Control Register */
#define PCR_ITSS_PIRQB_ROUT 0x3101
/* PIRQC Routing Control Register */
#define PCR_ITSS_PIRQC_ROUT 0x3102
/* PIRQD Routing Control Register */
#define PCR_ITSS_PIRQD_ROUT 0x3103
/* PIRQE Routing Control Register */
#define PCR_ITSS_PIRQE_ROUT 0x3104
/* PIRQF Routing Control Register */
#define PCR_ITSS_PIRQF_ROUT 0x3105
/* PIRQG Routing Control Register */
#define PCR_ITSS_PIRQG_ROUT 0x3106
/* PIRQH Routing Control Register */
#define PCR_ITSS_PIRQH_ROUT 0x3107
/* ITSS Interrupt polarity control */
#define PCR_ITSS_IPC0_CONF 0x3200
/* ITSS Power reduction control */
#define PCR_ITSS_ITSSPRC 0x3300
#endif /* _ASM_ARCH_ITSS_H */

View File

@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Intel Corporation.
* Take from coreboot project file of the same name
*/
#ifndef _ASM_ARCH_LPC_H
#define _ASM_ARCH_LPC_H
#define LPC_SERIRQ_CTL 0x64
#define LPC_SCNT_EN BIT(7)
#define LPC_SCNT_MODE BIT(6)
#define LPC_IO_DECODE 0x80
#define LPC_IOD_COMA_RANGE (0 << 0) /* 0x3F8 - 0x3FF COMA*/
#define LPC_IOD_COMB_RANGE (1 << 4) /* 0x2F8 - 0x2FF COMB*/
/*
* Use IO_<peripheral>_<IO port> style macros defined in lpc_lib.h
* to enable decoding of I/O locations for a peripheral
*/
#define LPC_IO_ENABLES 0x82
#define LPC_GENERIC_IO_RANGE(n) ((((n) & 0x3) * 4) + 0x84)
#define LPC_LGIR_AMASK_MASK (0xfc << 16)
#define LPC_LGIR_ADDR_MASK 0xfffc
#define LPC_LGIR_EN BIT(0)
#define LPC_LGIR_MAX_WINDOW_SIZE 256
#define LPC_GENERIC_MEM_RANGE 0x98
#define LPC_LGMR_ADDR_MASK 0xffff0000
#define LPC_LGMR_EN BIT(0)
#define LPC_LGMR_WINDOW_SIZE (64 * KiB)
#define LPC_BIOS_CNTL 0xdc
#define LPC_BC_BILD BIT(7)
#define LPC_BC_LE BIT(1)
#define LPC_BC_EISS BIT(5)
#define LPC_PCCTL 0xE0 /* PCI Clock Control */
#define LPC_PCCTL_CLKRUN_EN BIT(0)
/*
* IO decode enable macros are in the format IO_<peripheral>_<IO port>.
* For example, to open ports 0x60, 0x64 for the keyboard controller,
* use IOE_KBC_60_64 macro. For IOE_ macros that do not specify a port range,
* the port range is selectable via the IO decodes register.
*/
#define LPC_IOE_EC_4E_4F BIT(13)
#define LPC_IOE_SUPERIO_2E_2F BIT(12)
#define LPC_IOE_EC_62_66 BIT(11)
#define LPC_IOE_KBC_60_64 BIT(10)
#define LPC_IOE_HGE_208 BIT(9)
#define LPC_IOE_LGE_200 BIT(8)
#define LPC_IOE_FDD_EN BIT(3)
#define LPC_IOE_LPT_EN BIT(2)
#define LPC_IOE_COMB_EN BIT(1)
#define LPC_IOE_COMA_EN BIT(0)
#define LPC_NUM_GENERIC_IO_RANGES 4
#define LPC_IO_ENABLES 0x82
/**
* lpc_enable_fixed_io_ranges() - enable the fixed I/O ranges
*
* @io_enables: Mask of things to enable (LPC_IOE_.)
*/
void lpc_enable_fixed_io_ranges(uint io_enables);
/**
* lpc_open_pmio_window() - Open an IO port range
*
* @base: Base I/O address (e.g. 0x800)
* @size: Size of window (e.g. 0x100)
* @return 0 if OK, -ENOSPC if there are no more windows available, -EALREADY
* if already set up
*/
int lpc_open_pmio_window(uint base, uint size);
/**
* lpc_io_setup_comm_a_b() - Set up basic serial UARTs
*
* Set up the LPC to handle I/O to the COMA/COMB serial UART addresses
* 2f8-2ff and 3f8-3ff.
*/
void lpc_io_setup_comm_a_b(void);
#endif

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2019 Google LLC
*/
#ifndef _ASM_ARCH_PCH_H
#define _ASM_ARCH_PCH_H
#endif /* _ASM_ARCH_PCH_H */

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2015-2016 Intel Corp.
* (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
*/
#ifndef _ASM_ARCH_PM_H
#define _ASM_ARCH_PM_H
#define PMC_GPE_SW_31_0 0
#define PMC_GPE_SW_63_32 1
#define PMC_GPE_NW_31_0 3
#define PMC_GPE_NW_63_32 4
#define PMC_GPE_NW_95_64 5
#define PMC_GPE_N_31_0 6
#define PMC_GPE_N_63_32 7
#define PMC_GPE_W_31_0 9
#endif

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Intel Corporation.
* Take from coreboot project file of the same name
*/
#ifndef _ASM_ARCH_SYSTEMAGENT_H
#define _ASM_ARCH_SYSTEMAGENT_H
/* Device 0:0.0 PCI configuration space */
#define MCHBAR 0x48
/* RAPL Package Power Limit register under MCHBAR */
#define PUNIT_THERMAL_DEVICE_IRQ 0x700C
#define PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER 0x18
#define PUINT_THERMAL_DEVICE_IRQ_LOCK 0x80000000
#define BIOS_RESET_CPL 0x7078
#define PCODE_INIT_DONE BIT(8)
#define MCHBAR_RAPL_PPL 0x70A8
#define CORE_DISABLE_MASK 0x7168
#define CAPID0_A 0xE4
#define VTD_DISABLE BIT(23)
#define DEFVTBAR 0x6c80
#define GFXVTBAR 0x6c88
#define VTBAR_ENABLED 0x01
#define VTBAR_MASK GENMASK_ULL(39, 12)
#define VTBAR_SIZE 0x1000
/**
* enable_bios_reset_cpl() - Tell the system agent that memory/power are ready
*
* This should be called when U-Boot has set up the memory and power
* management.
*/
void enable_bios_reset_cpl(void);
#endif

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2019 Google LLC
*/
#ifndef _ASM_ARCH_UART_H
#define _ASM_ARCH_UART_H
/**
* apl_uart_init() - Set up the APL UART device and clock
*
* This enables the PCI device, sets up the MMIO region and turns on the clock
* using LPSS.
*
* The UART won't actually work unless the GPIO settings are correct and the
* signals actually exit the SoC. See board_debug_uart_init() for that.
*/
int apl_uart_init(pci_dev_t bdf, ulong base);
#endif

View File

@ -27,7 +27,6 @@
#define MSR_VR_CURRENT_CONFIG 0x601
#define MSR_VR_MISC_CONFIG 0x603
#define MSR_PKG_POWER_SKU 0x614
#define MSR_DDR_RAPL_LIMIT 0x618
#define MSR_VR_MISC_CONFIG2 0x636

View File

@ -43,7 +43,6 @@
#define MSR_PP1_CURRENT_CONFIG 0x602
#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */
#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */
#define MSR_PKG_POWER_SKU 0x614
#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
#define MSR_CONFIG_TDP_LEVEL1 0x649

View File

@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2017 Intel Corporation.
*/
#ifndef ASM_FAST_SPI_H
#define ASM_FAST_SPI_H
/* Register offsets from the MMIO region base (PCI_BASE_ADDRESS_0) */
struct fast_spi_regs {
u32 bfp;
u32 hsfsts_ctl;
u32 faddr;
u32 dlock;
u32 fdata[0x10];
u32 fracc;
u32 freg[12];
u32 fpr[5];
u32 gpr0;
u32 spare2;
u32 sts_ctl;
u16 preop;
u16 optype;
u8 opmenu[8];
u32 spare3;
u32 fdoc;
u32 fdod;
u32 spare4;
u32 afc;
u32 vscc[2];
u32 ptinx;
u32 ptdata;
};
check_member(fast_spi_regs, ptdata, 0xd0);
/* Bit definitions for BFPREG (0x00) register */
#define SPIBAR_BFPREG_PRB_MASK 0x7fff
#define SPIBAR_BFPREG_PRL_SHIFT 16
#define SPIBAR_BFPREG_PRL_MASK (0x7fff << SPIBAR_BFPREG_PRL_SHIFT)
/* PCI configuration registers */
#define SPIBAR_BIOS_CONTROL 0xdc
#define SPIBAR_BIOS_CONTROL_WPD BIT(0)
#define SPIBAR_BIOS_CONTROL_LOCK_ENABLE BIT(1)
#define SPIBAR_BIOS_CONTROL_CACHE_DISABLE BIT(2)
#define SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE BIT(3)
#define SPIBAR_BIOS_CONTROL_EISS BIT(5)
#define SPIBAR_BIOS_CONTROL_BILD BIT(7)
/**
* fast_spi_get_bios_mmap() - Get memory map for SPI flash
*
* @pdev: PCI device to use (this is the Fast SPI device)
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 (always)
*/
int fast_spi_get_bios_mmap(pci_dev_t pdev, ulong *map_basep, uint *map_sizep,
uint *offsetp);
int fast_spi_early_init(pci_dev_t pdev, ulong mmio_base);
#endif /* ASM_FAST_SPI_H */

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2019 Google LLC
*/
#ifndef __ASM_FSP_API_H
#define __ASM_FSP_API_H
enum fsp_phase {
/* Notification code for post PCI enuermation */
INIT_PHASE_PCI = 0x20,
/* Notification code before transferring control to the payload */
INIT_PHASE_BOOT = 0x40
};
struct fsp_notify_params {
/* Notification phase used for NotifyPhase API */
enum fsp_phase phase;
};
/* FspNotify API function prototype */
typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
#endif

View File

@ -143,13 +143,6 @@ int fsp_init_phase_pci(void);
*/
int fsp_scan_for_ram_size(void);
/**
* fsp_prepare_mrc_cache() - Find the DRAM training data from the MRC cache
*
* @return pointer to data, or NULL if no cache or no data found in the cache
*/
void *fsp_prepare_mrc_cache(void);
/**
* fsp_notify() - FSP notification wrapper function
*

View File

@ -4,11 +4,11 @@
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*/
#ifndef __FSP_API_H__
#define __FSP_API_H__
#ifndef __FSP1_API_H__
#define __FSP1_API_H__
#include <linux/linkage.h>
#include <asm/fsp/fsp_api.h>
/*
* FSP common configuration structure.
* This needs to be included in the platform-specific struct fsp_config_data.
@ -46,22 +46,7 @@ struct common_buf {
u32 reserved[6]; /* Reserved */
};
enum fsp_phase {
/* Notification code for post PCI enuermation */
INIT_PHASE_PCI = 0x20,
/* Notification code before transfering control to the payload */
INIT_PHASE_BOOT = 0x40
};
struct fsp_notify_params {
/* Notification phase used for NotifyPhase API */
enum fsp_phase phase;
};
/* FspInit API function prototype */
typedef asmlinkage u32 (*fsp_init_f)(struct fsp_init_params *params);
/* FspNotify API function prototype */
typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
#endif

View File

@ -0,0 +1,63 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright (C) 2015-2016 Intel Corp.
* (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
* (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
* Mostly taken from coreboot fsp2_0/memory_init.c
*/
#ifndef __ASM_FSP2_API_H
#define __ASM_FSP2_API_H
#include <asm/fsp/fsp_api.h>
struct fspm_upd;
struct fsps_upd;
struct hob_header;
enum fsp_boot_mode {
FSP_BOOT_WITH_FULL_CONFIGURATION = 0x00,
FSP_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01,
FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02,
FSP_BOOT_ON_S4_RESUME = 0x05,
FSP_BOOT_ON_S3_RESUME = 0x11,
FSP_BOOT_ON_FLASH_UPDATE = 0x12,
FSP_BOOT_IN_RECOVERY_MODE = 0x20
};
struct __packed fsp_upd_header {
u64 signature;
u8 revision;
u8 reserved[23];
};
/**
* fsp_memory_init() - Init the SDRAM
*
* @s3wake: true if we are booting from resume, so cannot reinit the mememory
* from scatch since we will lose its contents
* @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
* mapped SPI
* @return 0 if OK, -ve on error
*/
int fsp_memory_init(bool s3wake, bool use_spi_flash);
typedef asmlinkage int (*fsp_memory_init_func)(struct fspm_upd *params,
struct hob_header **hobp);
/**
* fsp_silicon_init() - Init the silicon
*
* This calls the FSP's 'silicon init' entry point
*
* @s3wake: true if we are booting from resume, so cannot reinit the mememory
* from scatch since we will lose its contents
* @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
* mapped SPI
* @return 0 if OK, -ve on error
*/
int fsp_silicon_init(bool s3wake, bool use_spi_flash);
typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
#endif

View File

@ -0,0 +1,97 @@
/* SPDX-License-Identifier: Intel */
/*
* Copyright (C) 2015-2016 Intel Corp.
* (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
* Mostly taken from coreboot
*/
#ifndef __ASM_FSP_INTERNAL_H
#define __ASM_FSP_INTERNAL_H
struct binman_entry;
struct fsp_header;
struct fspm_upd;
struct fsps_upd;
enum fsp_type_t {
FSP_M,
FSP_S,
};
int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
struct fsp_header **fspp);
/**
* fsp_locate_fsp() - Locate an FSP component
*
* This finds an FSP component by various methods. It is not as general-purpose
* as it looks, since it expects FSP-M to be requested in SPL (only), and FSP-S
* to be requested in U-Boot proper.
*
* @type: Component to locate
* @entry: Returns location of component
* @use_spi_flash: true to read using the Fast SPI driver, false to use
* memory-mapped SPI flash
* @devp: Returns northbridge device
* @hdrp: Returns FSP header
* @rom_offsetp: If non-NULL, returns the offset to add to any image position to
* find the memory-mapped location of that position. For example, for ROM
* position 0x1000, it will be mapped into 0x1000 + *rom_offsetp.
*/
int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
bool use_spi_flash, struct udevice **devp,
struct fsp_header **hdrp, ulong *rom_offsetp);
/**
* arch_fsps_preinit() - Perform init needed before calling FSP-S
*
* This allows use of probed drivers and PCI so is a convenient place to do any
* init that is needed before FSP-S is called. After this, U-Boot relocates and
* calls arch_fsp_init_r() before PCI is probed, and that function is not
* allowed to probe PCI before calling FSP-S.
*/
int arch_fsps_preinit(void);
/**
* fspm_update_config() - Set up the config structure for FSP-M
*
* @dev: Hostbridge device containing config
* @upd: Config data to fill in
* @return 0 if OK, -ve on error
*/
int fspm_update_config(struct udevice *dev, struct fspm_upd *upd);
/**
* fspm_done() - Indicate that memory init is complete
*
* This allows the board to do whatever post-init it needs before things
* continue.
*
* @dev: Hostbridge device
* @return 0 if OK, -ve on error
*/
int fspm_done(struct udevice *dev);
/**
* fsps_update_config() - Set up the config structure for FSP-S
*
* @dev: Hostbridge device containing config
* @rom_offset: Value to add to convert from ROM offset to memory-mapped address
* @upd: Config data to fill in
* @return 0 if OK, -ve on error
*/
int fsps_update_config(struct udevice *dev, ulong rom_offset,
struct fsps_upd *upd);
/**
* prepare_mrc_cache() - Read the MRC cache into the product-data struct
*
* This looks for cached Memory-reference code (MRC) data and stores it into
* @upd for use by the FSP-M binary.
*
* @return 0 if OK, -ENOENT if no data (whereupon the caller can continue and
* expect a slower boot), other -ve value on other error
*/
int prepare_mrc_cache(struct fspm_upd *upd);
#endif

View File

@ -10,6 +10,7 @@
#ifndef __ASSEMBLY__
#include <asm/processor.h>
#include <asm/mrccache.h>
enum pei_boot_mode_t {
PEI_BOOT_NONE = 0,
@ -66,6 +67,21 @@ struct mtrr_request {
uint64_t size;
};
/**
* struct mrc_output - holds the MRC data
*
* @buf: MRC training data to save for the next boot. This is set to point to
* the raw data after SDRAM init is complete. Then mrccache_setup()
* turns it into a proper cache record with a checksum
* @len: Length of @buf
* @cache: Resulting cache record
*/
struct mrc_output {
char *buf;
uint len;
struct mrc_data_container *cache;
};
/* Architecture-specific global data */
struct arch_global_data {
u64 gdt[X86_GDT_NUM_ENTRIES] __aligned(16);
@ -90,12 +106,12 @@ struct arch_global_data {
struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
int mtrr_req_count;
int has_mtrr;
/* MRC training data to save for the next boot */
char *mrc_output;
unsigned int mrc_output_len;
/* MRC training data */
struct mrc_output mrc[MRC_TYPE_COUNT];
ulong table; /* Table pointer from previous loader */
int turbo_state; /* Current turbo state */
struct irq_routing_table *pirq_routing_table;
int dw_i2c_num_cards; /* Used by designware i2c driver */
#ifdef CONFIG_SEABIOS
u32 high_table_ptr;
u32 high_table_limit;
@ -104,6 +120,9 @@ struct arch_global_data {
int prev_sleep_state; /* Previous sleep state ACPI_S0/1../5 */
ulong backup_mem; /* Backup memory address for S3 */
#endif
#ifdef CONFIG_FSP_VERSION2
struct fsp_header *fsp_s_hdr; /* Pointer to FSP-S header */
#endif
};
#endif

View File

@ -0,0 +1,306 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017 Intel Corporation.
* Copyright 2019 Google LLC
*
* Modified from coreboot gpio.h
*/
#ifndef __ASM_INTEL_PINCTRL_H
#define __ASM_INTEL_PINCTRL_H
#include <dm/pinctrl.h>
/**
* struct pad_config - config for a pad
* @pad: offset of pad within community
* @pad_config: Pad config data corresponding to DW0, DW1, etc.
*/
struct pad_config {
int pad;
u32 pad_config[4];
};
#include <asm/arch/gpio.h>
/* GPIO community IOSF sideband clock gating */
#define MISCCFG_GPSIDEDPCGEN BIT(5)
/* GPIO community RCOMP clock gating */
#define MISCCFG_GPRCOMPCDLCGEN BIT(4)
/* GPIO community RTC clock gating */
#define MISCCFG_GPRTCDLCGEN BIT(3)
/* GFX controller clock gating */
#define MISCCFG_GSXSLCGEN BIT(2)
/* GPIO community partition clock gating */
#define MISCCFG_GPDPCGEN BIT(1)
/* GPIO community local clock gating */
#define MISCCFG_GPDLCGEN BIT(0)
/* Enable GPIO community power management configuration */
#define MISCCFG_ENABLE_GPIO_PM_CONFIG (MISCCFG_GPSIDEDPCGEN | \
MISCCFG_GPRCOMPCDLCGEN | MISCCFG_GPRTCDLCGEN | MISCCFG_GSXSLCGEN \
| MISCCFG_GPDPCGEN | MISCCFG_GPDLCGEN)
/*
* GPIO numbers may not be contiguous and instead will have a different
* starting pin number for each pad group.
*/
#define INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
group_pad_base) \
{ \
.first_pad = (start_of_group) - (first_of_community), \
.size = (end_of_group) - (start_of_group) + 1, \
.acpi_pad_base = (group_pad_base), \
}
/*
* A pad base of -1 indicates that this group uses contiguous numbering
* and a pad base should not be used for this group.
*/
#define PAD_BASE_NONE -1
/* The common/default group numbering is contiguous */
#define INTEL_GPP(first_of_community, start_of_group, end_of_group) \
INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
PAD_BASE_NONE)
/**
* struct reset_mapping - logical to actual value for PADRSTCFG in DW0
*
* Note that the values are expected to be within the field placement of the
* register itself. i.e. if the reset field is at 31:30 then the values within
* logical and chipset should occupy 31:30.
*/
struct reset_mapping {
u32 logical;
u32 chipset;
};
/**
* struct pad_group - describes the groups within each community
*
* @first_pad: offset of first pad of the group relative to the community
* @size: size of the group
* @acpi_pad_base: starting pin number for the pads in this group when they are
* used in ACPI. This is only needed if the pins are not contiguous across
* groups. Most groups will have this set to PAD_BASE_NONE and use
* contiguous numbering for ACPI.
*/
struct pad_group {
int first_pad;
uint size;
int acpi_pad_base;
};
/**
* struct pad_community - community of pads
*
* This describes a community, or each group within a community when multiple
* groups exist inside a community
*
* @name: Community name
* @acpi_path: ACPI path
* @num_gpi_regs: number of gpi registers in community
* @max_pads_per_group: number of pads in each group; number of pads bit-mapped
* in each GPI status/en and Host Own Reg
* @first_pad: first pad in community
* @last_pad: last pad in community
* @host_own_reg_0: offset to Host Ownership Reg 0
* @gpi_int_sts_reg_0: offset to GPI Int STS Reg 0
* @gpi_int_en_reg_0: offset to GPI Int Enable Reg 0
* @gpi_smi_sts_reg_0: offset to GPI SMI STS Reg 0
* @gpi_smi_en_reg_0: offset to GPI SMI EN Reg 0
* @pad_cfg_base: offset to first PAD_GFG_DW0 Reg
* @gpi_status_offset: specifies offset in struct gpi_status
* @port: PCR Port ID
* @reset_map: PADRSTCFG logical to chipset mapping
* @num_reset_vals: number of values in @reset_map
* @groups; list of groups for this community
* @num_groups: number of groups
*/
struct pad_community {
const char *name;
const char *acpi_path;
size_t num_gpi_regs;
size_t max_pads_per_group;
uint first_pad;
uint last_pad;
u16 host_own_reg_0;
u16 gpi_int_sts_reg_0;
u16 gpi_int_en_reg_0;
u16 gpi_smi_sts_reg_0;
u16 gpi_smi_en_reg_0;
u16 pad_cfg_base;
u8 gpi_status_offset;
u8 port;
const struct reset_mapping *reset_map;
size_t num_reset_vals;
const struct pad_group *groups;
size_t num_groups;
};
/**
* struct intel_pinctrl_priv - private data for each pinctrl device
*
* @comm: Pad community for this device
* @num_cfgs: Number of configuration words for each pad
* @itss: ITSS device (for interrupt handling)
* @itss_pol_cfg: Use to program Interrupt Polarity Control (IPCx) register
* Each bit represents IRQx Active High Polarity Disable configuration:
* when set to 1, the interrupt polarity associated with IRQx is inverted
* to appear as Active Low to IOAPIC and vice versa
*/
struct intel_pinctrl_priv {
const struct pad_community *comm;
int num_cfgs;
struct udevice *itss;
bool itss_pol_cfg;
};
/* Exported common operations for the pinctrl driver */
extern const struct pinctrl_ops intel_pinctrl_ops;
/* Exported common probe function for the pinctrl driver */
int intel_pinctrl_probe(struct udevice *dev);
/**
* intel_pinctrl_ofdata_to_platdata() - Handle common platdata setup
*
* @dev: Pinctrl device
* @comm: Pad community for this device
* @num_cfgs: Number of configuration words for each pad
* @return 0 if OK, -EDOM if @comm is NULL, other -ve value on other error
*/
int intel_pinctrl_ofdata_to_platdata(struct udevice *dev,
const struct pad_community *comm,
int num_cfgs);
/**
* pinctrl_route_gpe() - set GPIO groups for the general-purpose-event blocks
*
* The values from PMC register GPE_CFG are passed which is then mapped to
* proper groups for MISCCFG. This basically sets the MISCCFG register bits:
* dw0 = gpe0_route[11:8]. This is ACPI GPE0b.
* dw1 = gpe0_route[15:12]. This is ACPI GPE0c.
* dw2 = gpe0_route[19:16]. This is ACPI GPE0d.
*
* @dev: ITSS device
* @gpe0b: Value for GPE0B
* @gpe0c: Value for GPE0C
* @gpe0d: Value for GPE0D
* @return 0 if OK, -ve on error
*/
int pinctrl_route_gpe(struct udevice *dev, uint gpe0b, uint gpe0c, uint gpe0d);
/**
* pinctrl_config_pads() - Configure a list of pads
*
* Configures multiple pads using the provided data from the device tree.
*
* @dev: pinctrl device (any will do)
* @pads: Pad data, consisting of a pad number followed by num_cfgs entries
* containing the data for that pad (num_cfgs is set by the pinctrl device)
* @pads_count: Number of pads to configure
* @return 0 if OK, -ve on error
*/
int pinctrl_config_pads(struct udevice *dev, u32 *pads, int pads_count);
/**
* pinctrl_gpi_clear_int_cfg() - Set up the interrupts for use
*
* This enables the interrupt inputs and clears the status register bits
*
* @return 0 if OK, -ve on error
*/
int pinctrl_gpi_clear_int_cfg(void);
/**
* pinctrl_config_pads_for_node() - Configure pads
*
* Set up the pads using the data in a given node
*
* @dev: pinctrl device (any will do)
* @node: Node containing the 'pads' property with the data in it
* @return 0 if OK, -ve on error
*/
int pinctrl_config_pads_for_node(struct udevice *dev, ofnode node);
/**
* pinctrl_read_pads() - Read pad data from a node
*
* @dev: pinctrl device (any will do, it is just used to get config)
* @node: Node to read pad data from
* @prop: Property name to use (e.g. "pads")
* @padsp: Returns a pointer to an allocated array of pad data, in the format:
* <pad>
* <pad_config0>
* <pad_config1>
* ...
*
* The number of pad config values is set by the pinctrl controller.
* The caller must free this array.
* @pad_countp: Returns the number of pads read
* @ereturn 0 if OK, -ve on error
*/
int pinctrl_read_pads(struct udevice *dev, ofnode node, const char *prop,
u32 **padsp, int *pad_countp);
/**
* pinctrl_count_pads() - Count the number of pads in a pad array
*
* This used used with of-platdata where the array may be smaller than its
* maximum size. This function searches for the last pad in the array by finding
* the first 'zero' record
*
* This works out the number of records in the array. Each record has one word
* for the pad and num_cfgs words for the config.
*
* @dev: pinctrl device (any will do)
* @pads: Array of pad data
* @size: Size of pad data in bytes
* @return number of pads represented by the data
*/
int pinctrl_count_pads(struct udevice *dev, u32 *pads, int size);
/**
* intel_pinctrl_get_config_reg_addr() - Get address of the pin config registers
*
* @dev: Pinctrl device
* @offset: GPIO offset within this device
* @return register offset within the GPIO p2sb region
*/
u32 intel_pinctrl_get_config_reg_addr(struct udevice *dev, uint offset);
/**
* intel_pinctrl_get_config_reg() - Get the value of a GPIO register
*
* @dev: Pinctrl device
* @offset: GPIO offset within this device
* @return register value within the GPIO p2sb region
*/
u32 intel_pinctrl_get_config_reg(struct udevice *dev, uint offset);
/**
* intel_pinctrl_get_pad() - Get pad information for a pad
*
* This is used by the GPIO controller to find the pinctrl used by a pad.
*
* @pad: Pad to check
* @devp: Returns pinctrl device containing that pad
* @offsetp: Returns offset of pad within that pinctrl device
*/
int intel_pinctrl_get_pad(uint pad, struct udevice **devp, uint *offsetp);
/**
* intel_pinctrl_get_acpi_pin() - Get the ACPI pin for a pinctrl pin
*
* Maps a pinctrl pin (in terms of its offset within the pins controlled by that
* pinctrl) to an ACPI GPIO pin-table entry.
*
* @dev: Pinctrl device to check
* @offset: Offset of pin within that device (0 = first)
* @return associated ACPI GPIO pin-table entry, or standard pin number if the
* ACPI pad base is not set
*/
int intel_pinctrl_get_acpi_pin(struct udevice *dev, uint offset);
#endif

View File

@ -0,0 +1,373 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015-2016 Intel Corp.
* Copyright 2019 Google LLC
*
* Modified from coreboot gpio_defs.h
*/
#ifndef _ASM_INTEL_PINCTRL_DEFS_H_
#define _ASM_INTEL_PINCTRL_DEFS_H_
/* This file is included by device trees, so avoid BIT() macros */
#define PAD_CFG0_TX_STATE_BIT 0
#define PAD_CFG0_TX_STATE (1 << PAD_CFG0_TX_STATE_BIT)
#define PAD_CFG0_RX_STATE_BIT 1
#define PAD_CFG0_RX_STATE (1 << PAD_CFG0_RX_STATE_BIT)
#define PAD_CFG0_TX_DISABLE (1 << 8)
#define PAD_CFG0_RX_DISABLE (1 << 9)
#define PAD_CFG0_MODE_SHIFT 10
#define PAD_CFG0_MODE_MASK (7 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_GPIO (0 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF1 (1 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF2 (2 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF3 (3 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF4 (4 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF5 (5 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_MODE_NF6 (6 << PAD_CFG0_MODE_SHIFT)
#define PAD_CFG0_ROUTE_MASK (0xf << 17)
#define PAD_CFG0_ROUTE_NMI (1 << 17)
#define PAD_CFG0_ROUTE_SMI (1 << 18)
#define PAD_CFG0_ROUTE_SCI (1 << 19)
#define PAD_CFG0_ROUTE_IOAPIC (1 << 20)
#define PAD_CFG0_RXTENCFG_MASK (3 << 21)
#define PAD_CFG0_RXINV_MASK (1 << 23)
#define PAD_CFG0_RX_POL_INVERT (1 << 23)
#define PAD_CFG0_RX_POL_NONE (0 << 23)
#define PAD_CFG0_PREGFRXSEL (1 << 24)
#define PAD_CFG0_TRIG_MASK (3 << 25)
#define PAD_CFG0_TRIG_LEVEL (0 << 25)
#define PAD_CFG0_TRIG_EDGE_SINGLE (1 << 25) /* controlled by RX_INVERT*/
#define PAD_CFG0_TRIG_OFF (2 << 25)
#define PAD_CFG0_TRIG_EDGE_BOTH (3 << 25)
#define PAD_CFG0_RXRAW1_MASK (1 << 28)
#define PAD_CFG0_RXPADSTSEL_MASK (1 << 29)
#define PAD_CFG0_RESET_MASK (3 << 30)
#define PAD_CFG0_LOGICAL_RESET_PWROK (0U << 30)
#define PAD_CFG0_LOGICAL_RESET_DEEP (1U << 30)
#define PAD_CFG0_LOGICAL_RESET_PLTRST (2U << 30)
#define PAD_CFG0_LOGICAL_RESET_RSMRST (3U << 30)
/*
* Use the fourth bit in IntSel field to indicate gpio ownership. This field is
* RO and hence not used during gpio configuration.
*/
#define PAD_CFG1_GPIO_DRIVER (0x1 << 4)
#define PAD_CFG1_IRQ_MASK (0xff << 0)
#define PAD_CFG1_IOSTERM_MASK (0x3 << 8)
#define PAD_CFG1_IOSTERM_SAME (0x0 << 8)
#define PAD_CFG1_IOSTERM_DISPUPD (0x1 << 8)
#define PAD_CFG1_IOSTERM_ENPD (0x2 << 8)
#define PAD_CFG1_IOSTERM_ENPU (0x3 << 8)
#define PAD_CFG1_PULL_MASK (0xf << 10)
#define PAD_CFG1_PULL_NONE (0x0 << 10)
#define PAD_CFG1_PULL_DN_5K (0x2 << 10)
#define PAD_CFG1_PULL_DN_20K (0x4 << 10)
#define PAD_CFG1_PULL_UP_1K (0x9 << 10)
#define PAD_CFG1_PULL_UP_5K (0xa << 10)
#define PAD_CFG1_PULL_UP_2K (0xb << 10)
#define PAD_CFG1_PULL_UP_20K (0xc << 10)
#define PAD_CFG1_PULL_UP_667 (0xd << 10)
#define PAD_CFG1_PULL_NATIVE (0xf << 10)
/* Tx enabled driving last value driven, Rx enabled */
#define PAD_CFG1_IOSSTATE_TX_LAST_RXE (0x0 << 14)
/*
* Tx enabled driving 0, Rx disabled and Rx driving 0 back to its controller
* internally
*/
#define PAD_CFG1_IOSSTATE_TX0_RX_DCR_X0 (0x1 << 14)
/*
* Tx enabled driving 0, Rx disabled and Rx driving 1 back to its controller
* internally
*/
#define PAD_CFG1_IOSSTATE_TX0_RX_DCR_X1 (0x2 << 14)
/*
* Tx enabled driving 1, Rx disabled and Rx driving 0 back to its controller
* internally
*/
#define PAD_CFG1_IOSSTATE_TX1_RX_DCR_X0 (0x3 << 14)
/*
* Tx enabled driving 1, Rx disabled and Rx driving 1 back to its controller
* internally
*/
#define PAD_CFG1_IOSSTATE_TX1_RX_DCR_X1 (0x4 << 14)
/* Tx enabled driving 0, Rx enabled */
#define PAD_CFG1_IOSSTATE_TX0_RXE (0x5 << 14)
/* Tx enabled driving 1, Rx enabled */
#define PAD_CFG1_IOSSTATE_TX1_RXE (0x6 << 14)
/* Hi-Z, Rx driving 0 back to its controller internally */
#define PAD_CFG1_IOSSTATE_HIZCRX0 (0x7 << 14)
/* Hi-Z, Rx driving 1 back to its controller internally */
#define PAD_CFG1_IOSSTATE_HIZCRX1 (0x8 << 14)
/* Tx disabled, Rx enabled */
#define PAD_CFG1_IOSSTATE_TXD_RXE (0x9 << 14)
#define PAD_CFG1_IOSSTATE_IGNORE (0xf << 14) /* Ignore Iostandby */
/* mask to extract Iostandby bits */
#define PAD_CFG1_IOSSTATE_MASK (0xf << 14)
#define PAD_CFG1_IOSSTATE_SHIFT 14 /* set Iostandby bits [17:14] */
#define PAD_CFG2_DEBEN 1
/* Debounce Duration = (2 ^ PAD_CFG2_DEBOUNCE_x_RTC) * RTC clock duration */
#define PAD_CFG2_DEBOUNCE_8_RTC (0x3 << 1)
#define PAD_CFG2_DEBOUNCE_16_RTC (0x4 << 1)
#define PAD_CFG2_DEBOUNCE_32_RTC (0x5 << 1)
#define PAD_CFG2_DEBOUNCE_64_RTC (0x6 << 1)
#define PAD_CFG2_DEBOUNCE_128_RTC (0x7 << 1)
#define PAD_CFG2_DEBOUNCE_256_RTC (0x8 << 1)
#define PAD_CFG2_DEBOUNCE_512_RTC (0x9 << 1)
#define PAD_CFG2_DEBOUNCE_1K_RTC (0xa << 1)
#define PAD_CFG2_DEBOUNCE_2K_RTC (0xb << 1)
#define PAD_CFG2_DEBOUNCE_4K_RTC (0xc << 1)
#define PAD_CFG2_DEBOUNCE_8K_RTC (0xd << 1)
#define PAD_CFG2_DEBOUNCE_16K_RTC (0xe << 1)
#define PAD_CFG2_DEBOUNCE_32K_RTC (0xf << 1)
#define PAD_CFG2_DEBOUNCE_MASK 0x1f
/* voltage tolerance 0=3.3V default 1=1.8V tolerant */
#if IS_ENABLED(INTEL_PINCTRL_IOSTANDBY)
#define PAD_CFG1_TOL_MASK (0x1 << 25)
#define PAD_CFG1_TOL_1V8 (0x1 << 25)
#endif
#define PAD_FUNC(value) PAD_CFG0_MODE_##value
#define PAD_RESET(value) PAD_CFG0_LOGICAL_RESET_##value
#define PAD_PULL(value) PAD_CFG1_PULL_##value
#define PAD_IOSSTATE(value) PAD_CFG1_IOSSTATE_##value
#define PAD_IOSTERM(value) PAD_CFG1_IOSTERM_##value
#define PAD_IRQ_CFG(route, trig, inv) \
(PAD_CFG0_ROUTE_##route | \
PAD_CFG0_TRIG_##trig | \
PAD_CFG0_RX_POL_##inv)
#if IS_ENABLED(INTEL_PINCTRL_DUAL_ROUTE_SUPPORT)
#define PAD_IRQ_CFG_DUAL_ROUTE(route1, route2, trig, inv) \
(PAD_CFG0_ROUTE_##route1 | \
PAD_CFG0_ROUTE_##route2 | \
PAD_CFG0_TRIG_##trig | \
PAD_CFG0_RX_POL_##inv)
#endif /* CONFIG_INTEL_PINCTRL_DUAL_ROUTE_SUPPORT */
#define _PAD_CFG_STRUCT(__pad, __config0, __config1) \
__pad(__config0) (__config1)
/* Native function configuration */
#define PAD_CFG_NF(pad, pull, rst, func) \
_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
PAD_IOSSTATE(TX_LAST_RXE))
#if IS_ENABLED(CONFIG_INTEL_GPIO_PADCFG_PADTOL)
/*
* Native 1.8V tolerant pad, only applies to some pads like I2C/I2S. Not
* applicable to all SOCs. Refer EDS.
*/
#define PAD_CFG_NF_1V8(pad, pull, rst, func) \
_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) |\
PAD_IOSSTATE(TX_LAST_RXE) | PAD_CFG1_TOL_1V8)
#endif
/* Native function configuration for standby state */
#define PAD_CFG_NF_IOSSTATE(pad, pull, rst, func, iosstate) \
_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate))
/*
* Native function configuration for standby state, also configuring iostandby
* as masked
*/
#define PAD_CFG_NF_IOSTANDBY_IGNORE(pad, pull, rst, func) \
_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
PAD_IOSSTATE(IGNORE))
/*
* Native function configuration for standby state, also configuring iosstate
* and iosterm
*/
#define PAD_CFG_NF_IOSSTATE_IOSTERM(pad, pull, rst, func, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
/* General purpose output, no pullup/down */
#define PAD_CFG_GPO(pad, val, rst) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
PAD_PULL(NONE) | PAD_IOSSTATE(TX_LAST_RXE))
/* General purpose output, with termination specified */
#define PAD_CFG_TERM_GPO(pad, val, pull, rst) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
PAD_PULL(pull) | PAD_IOSSTATE(TX_LAST_RXE))
/* General purpose output, no pullup/down */
#define PAD_CFG_GPO_GPIO_DRIVER(pad, val, rst, pull) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
PAD_PULL(pull) | PAD_IOSSTATE(TX_LAST_RXE) | \
PAD_CFG1_GPIO_DRIVER)
/* General purpose output */
#define PAD_CFG_GPO_IOSSTATE_IOSTERM(pad, val, rst, pull, iosstate, ioterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
PAD_PULL(pull) | PAD_IOSSTATE(iosstate) | PAD_IOSTERM(ioterm))
/* General purpose input */
#define PAD_CFG_GPI(pad, pull, rst) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
/* General purpose input. The following macro sets the
* Host Software Pad Ownership to GPIO Driver mode.
*/
#define PAD_CFG_GPI_GPIO_DRIVER(pad, pull, rst) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
#define PAD_CFG_GPIO_DRIVER_HI_Z(pad, pull, rst, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_CFG0_RX_DISABLE, \
PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
#define PAD_CFG_GPIO_HI_Z(pad, pull, rst, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_CFG0_RX_DISABLE, PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
/* GPIO Interrupt */
#define PAD_CFG_GPI_INT(pad, pull, rst, trig) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_CFG0_TRIG_##trig | PAD_CFG0_RX_POL_NONE, \
PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
/*
* No Connect configuration for unused pad.
* Both TX and RX are disabled. RX disabling is done to avoid unnecessary
* setting of GPI_STS.
*/
#define PAD_NC(pad, pull) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(DEEP) | \
PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE, \
PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
/* General purpose input, routed to APIC */
#define PAD_CFG_GPI_APIC(pad, pull, rst, trig, inv) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(IOAPIC, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(TXD_RXE))
/* General purpose input, routed to APIC - with IOStandby Config*/
#define PAD_CFG_GPI_APIC_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(IOAPIC, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
/*
* The following APIC macros assume the APIC will handle the filtering
* on its own end. One just needs to pass an active high message into the
* ITSS.
*/
#define PAD_CFG_GPI_APIC_LOW(pad, pull, rst) \
PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, INVERT)
#define PAD_CFG_GPI_APIC_HIGH(pad, pull, rst) \
PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, NONE)
#define PAD_CFG_GPI_APIC_EDGE_LOW(pad, pull, rst) \
PAD_CFG_GPI_APIC(pad, pull, rst, EDGE_SINGLE, INVERT)
/* General purpose input, routed to SMI */
#define PAD_CFG_GPI_SMI(pad, pull, rst, trig, inv) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SMI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(TXD_RXE))
/* General purpose input, routed to SMI */
#define PAD_CFG_GPI_SMI_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SMI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
#define PAD_CFG_GPI_SMI_LOW(pad, pull, rst, trig) \
PAD_CFG_GPI_SMI(pad, pull, rst, trig, INVERT)
#define PAD_CFG_GPI_SMI_HIGH(pad, pull, rst, trig) \
PAD_CFG_GPI_SMI(pad, pull, rst, trig, NONE)
/* General purpose input, routed to SCI */
#define PAD_CFG_GPI_SCI(pad, pull, rst, trig, inv) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(TXD_RXE))
/* General purpose input, routed to SCI */
#define PAD_CFG_GPI_SCI_IOS(pad, pull, rst, trig, inv, iosstate, iosterm) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(iosstate) | PAD_IOSTERM(iosterm))
#define PAD_CFG_GPI_SCI_LOW(pad, pull, rst, trig) \
PAD_CFG_GPI_SCI(pad, pull, rst, trig, INVERT)
#define PAD_CFG_GPI_SCI_HIGH(pad, pull, rst, trig) \
PAD_CFG_GPI_SCI(pad, pull, rst, trig, NONE)
#define PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, inv, dur) \
_PAD_CFG_STRUCT_3(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(TXD_RXE), PAD_CFG2_DEBEN | PAD_CFG2_##dur)
#define PAD_CFG_GPI_SCI_LOW_DEBEN(pad, pull, rst, trig, dur) \
PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, INVERT, dur)
#define PAD_CFG_GPI_SCI_HIGH_DEBEN(pad, pull, rst, trig, dur) \
PAD_CFG_GPI_SCI_DEBEN(pad, pull, rst, trig, NONE, dur)
/* General purpose input, routed to NMI */
#define PAD_CFG_GPI_NMI(pad, pull, rst, trig, inv) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(NMI, trig, inv), PAD_PULL(pull) | \
PAD_IOSSTATE(TXD_RXE))
#if IS_ENABLED(INTEL_PINCTRL_DUAL_ROUTE_SUPPORT)
/* GPI, GPIO Driver, SCI interrupt */
#define PAD_CFG_GPI_GPIO_DRIVER_SCI(pad, pull, rst, trig, inv) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG(SCI, trig, inv), \
PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TXD_RXE))
#define PAD_CFG_GPI_DUAL_ROUTE(pad, pull, rst, trig, inv, route1, route2) \
_PAD_CFG_STRUCT(pad, \
PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
PAD_IRQ_CFG_DUAL_ROUTE(route1, route2, trig, inv), \
PAD_PULL(pull) | PAD_IOSSTATE(TXD_RXE))
#define PAD_CFG_GPI_IRQ_WAKE(pad, pull, rst, trig, inv) \
PAD_CFG_GPI_DUAL_ROUTE(pad, pull, rst, trig, inv, IOAPIC, SCI)
#endif /* CONFIG_INTEL_PINCTRL_DUAL_ROUTE_SUPPORT */
#endif /* _ASM_INTEL_PINCTRL_DEFS_H_ */

View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2019 Google LLC
*/
#ifndef __ASM_LPSS_H
#define __ASM_LPSS_H
struct udevice;
/* D0 and D3 enable config */
enum lpss_pwr_state {
STATE_D0 = 0,
STATE_D3 = 3
};
/**
* lpss_reset_release() - Release device from reset
*
* This is used for devices which have LPSS support.
*
* @regs: Pointer to device registers
*/
void lpss_reset_release(void *regs);
/**
* lpss_set_power_state() - Change power state of a device
*
* This is used for devices which have LPSS support.
*
* @dev: Device to update
* @state: New power state to set
*/
void lpss_set_power_state(struct udevice *dev, enum lpss_pwr_state state);
#endif

View File

@ -7,7 +7,7 @@
#ifndef _ASM_MRCCACHE_H
#define _ASM_MRCCACHE_H
#define MRC_DATA_ALIGN 0x1000
#define MRC_DATA_ALIGN 0x100
#define MRC_DATA_SIGNATURE (('M' << 0) | ('R' << 8) | \
('C' << 16) | ('D'<<24))
@ -27,6 +27,14 @@ struct mrc_region {
u32 length;
};
/* Types of MRC data */
enum mrc_type_t {
MRC_TYPE_NORMAL,
MRC_TYPE_VAR,
MRC_TYPE_COUNT,
};
struct udevice;
/**
@ -40,21 +48,6 @@ struct udevice;
*/
struct mrc_data_container *mrccache_find_current(struct mrc_region *entry);
/**
* mrccache_update() - update the MRC cache with a new record
*
* This writes a new record to the end of the MRC cache region. If the new
* record is the same as the latest record then the write is skipped
*
* @sf: SPI flash to write to
* @entry: Position and size of MRC cache in SPI flash
* @cur: Record to write
* @return 0 if updated, -EEXIST if the record is the same as the latest
* record, -EINVAL if the record is not valid, other error if SPI write failed
*/
int mrccache_update(struct udevice *sf, struct mrc_region *entry,
struct mrc_data_container *cur);
/**
* mrccache_reserve() - reserve MRC data on the stack
*
@ -84,6 +77,7 @@ int mrccache_reserve(void);
* triggers PCI bus enumeration during which insufficient memory issue
* might be exposed and it causes subsequent SPI flash probe fails).
*
* @type: Type of MRC data to use
* @devp: Returns pointer to the SPI flash device
* @entry: Position and size of MRC cache in SPI flash
* @return 0 if success, -ENOENT if SPI flash node does not exist in the
@ -91,7 +85,8 @@ int mrccache_reserve(void);
* tree, -EINVAL if MRC region properties format is incorrect, other error
* if SPI flash probe failed.
*/
int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
struct mrc_region *entry);
/**
* mrccache_save() - save MRC data to the SPI flash

View File

@ -70,6 +70,7 @@
#define MSR_IA32_BBL_CR_CTL 0x00000119
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
#define MSR_POWER_MISC 0x00000120
#define FLUSH_DL1_L2 (1 << 8)
#define ENABLE_ULFM_AUTOCM_MASK (1 << 2)
#define ENABLE_INDP_AUTOCM_MASK (1 << 3)
@ -241,10 +242,17 @@
#define PKG_POWER_LIMIT_CLAMP (1 << 16)
#define PKG_POWER_LIMIT_TIME_SHIFT 17
#define PKG_POWER_LIMIT_TIME_MASK 0x7f
/*
* For Mobile, RAPL default PL1 time window value set to 28 seconds.
* RAPL time window calculation defined as follows:
* Time Window = (float)((1+X/4)*(2*^Y), X Corresponds to [23:22],
* Y to [21:17] in MSR 0x610. 28 sec is equal to 0x6e.
*/
#define MB_POWER_LIMIT1_TIME_DEFAULT 0x6e
#define MSR_PKG_ENERGY_STATUS 0x00000611
#define MSR_PKG_PERF_STATUS 0x00000613
#define MSR_PKG_POWER_INFO 0x00000614
#define MSR_PKG_POWER_SKU 0x614
#define MSR_DRAM_POWER_LIMIT 0x00000618
#define MSR_DRAM_ENERGY_STATUS 0x00000619

View File

@ -25,8 +25,6 @@
/* Length of the public header on Intel microcode blobs */
#define UCODE_HEADER_LEN 0x30
#ifndef __ASSEMBLY__
/*
* This register is documented in (for example) the Intel Atom Processor E3800
* Product Family Datasheet in "PCU - Power Management Controller (PMC)".
@ -37,11 +35,11 @@
*/
#define IO_PORT_RESET 0xcf9
enum {
SYS_RST = 1 << 1, /* 0 for soft reset, 1 for hard reset */
RST_CPU = 1 << 2, /* initiate reset */
FULL_RST = 1 << 3, /* full power cycle */
};
#define SYS_RST (1 << 1) /* 0 for soft reset, 1 for hard reset */
#define RST_CPU (1 << 2) /* initiate reset */
#define FULL_RST (1 << 3) /* full power cycle */
#ifndef __ASSEMBLY__
static inline __attribute__((always_inline)) void cpu_hlt(void)
{

View File

@ -11,6 +11,7 @@
enum {
BOOT_DEVICE_SPI_MMAP = 10,
BOOT_DEVICE_FAST_SPI,
BOOT_DEVICE_CROS_VBOOT,
};

View File

@ -4,9 +4,11 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
ifndef CONFIG_X86_64
ifndef CONFIG_TPL_BUILD
obj-y += bios.o
obj-y += bios_asm.o
obj-y += bios_interrupts.o
endif
obj-y += string.o
endif
ifndef CONFIG_SPL_BUILD

View File

@ -4,4 +4,7 @@
obj-y += fsp_common.o
obj-y += fsp_dram.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
endif
obj-y += fsp_support.o

View File

@ -58,26 +58,6 @@ void board_final_cleanup(void)
debug("OK\n");
}
void *fsp_prepare_mrc_cache(void)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
if (ret)
return NULL;
cache = mrccache_find_current(&entry);
if (!cache)
return NULL;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
return cache->data;
}
#ifdef CONFIG_HAVE_ACPI_RESUME
int fsp_save_s3_stack(void)
{

View File

@ -9,6 +9,7 @@
#include <asm/fsp/fsp_support.h>
#include <asm/e820.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/post.h>
DECLARE_GLOBAL_DATA_PTR;
@ -38,8 +39,40 @@ int fsp_scan_for_ram_size(void)
int dram_init_banksize(void)
{
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
phys_addr_t low_end;
uint bank;
low_end = 0;
for (bank = 1, hdr = gd->arch.hob_list;
bank < CONFIG_NR_DRAM_BANKS && !end_of_hob(hdr);
hdr = get_next_hob(hdr)) {
if (hdr->type != HOB_TYPE_RES_DESC)
continue;
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type != RES_SYS_MEM &&
res_desc->type != RES_MEM_RESERVED)
continue;
if (res_desc->phys_start < (1ULL << 32)) {
low_end = max(low_end,
res_desc->phys_start + res_desc->len);
continue;
}
gd->bd->bi_dram[bank].start = res_desc->phys_start;
gd->bd->bi_dram[bank].size = res_desc->len;
mtrr_add_request(MTRR_TYPE_WRBACK, res_desc->phys_start,
res_desc->len);
log_debug("ram %llx %llx\n", gd->bd->bi_dram[bank].start,
gd->bd->bi_dram[bank].size);
}
/* Add the memory below 4GB */
gd->bd->bi_dram[0].start = 0;
gd->bd->bi_dram[0].size = gd->ram_size;
gd->bd->bi_dram[0].size = low_end;
mtrr_add_request(MTRR_TYPE_WRBACK, 0, low_end);
return 0;
}

View File

@ -7,7 +7,8 @@
#include <dm.h>
#include <vbe.h>
#include <video.h>
#include <asm/fsp1/fsp_support.h>
#include <asm/fsp/fsp_support.h>
#include <asm/mtrr.h>
DECLARE_GLOBAL_DATA_PTR;
@ -97,6 +98,9 @@ static int fsp_video_probe(struct udevice *dev)
if (ret)
goto err;
mtrr_add_request(MTRR_TYPE_WRCOMB, vesa->phys_base_ptr, 256 << 20);
mtrr_commit(true);
printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
vesa->bits_per_pixel);

View File

@ -5,7 +5,7 @@
*/
#include <common.h>
#include <asm/fsp1/fsp_support.h>
#include <asm/fsp/fsp_support.h>
#include <asm/post.h>
u32 fsp_get_usable_lowmem_top(const void *hob_list)

View File

@ -5,5 +5,4 @@
obj-y += fsp_car.o
obj-y += fsp_common.o
obj-y += fsp_dram.o
obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
obj-y += fsp_support.o

View File

@ -18,6 +18,26 @@
DECLARE_GLOBAL_DATA_PTR;
static void *fsp_prepare_mrc_cache(void)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
if (ret)
return NULL;
cache = mrccache_find_current(&entry);
if (!cache)
return NULL;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
return cache->data;
}
int arch_fsp_init(void)
{
void *nvs;

View File

@ -15,9 +15,11 @@ int dram_init(void)
if (ret)
return ret;
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
&gd->arch.mrc_output_len);
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
mrc->buf = fsp_get_nvs_data(gd->arch.hob_list, &mrc->len);
}
return 0;
}

View File

@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2019 Google LLC
obj-y += fsp_common.o
obj-y += fsp_dram.o
obj-y += fsp_init.o
obj-y += fsp_meminit.o
obj-y += fsp_silicon_init.o
obj-y += fsp_support.o

View File

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <init.h>
int arch_fsp_init(void)
{
return 0;
}

View File

@ -0,0 +1,78 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <acpi_s3.h>
#include <handoff.h>
#include <spl.h>
#include <asm/arch/cpu.h>
#include <asm/fsp/fsp_support.h>
#include <asm/fsp2/fsp_api.h>
#include <asm/fsp2/fsp_internal.h>
int dram_init(void)
{
int ret;
if (spl_phase() == PHASE_SPL) {
#ifdef CONFIG_HAVE_ACPI_RESUME
bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
#else
bool s3wake = false;
#endif
ret = fsp_memory_init(s3wake,
IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH));
if (ret) {
debug("Memory init failed (err=%x)\n", ret);
return ret;
}
/* The FSP has already set up DRAM, so grab the info we need */
ret = fsp_scan_for_ram_size();
if (ret)
return ret;
#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc[MRC_TYPE_NORMAL].buf =
fsp_get_nvs_data(gd->arch.hob_list,
&gd->arch.mrc[MRC_TYPE_NORMAL].len);
gd->arch.mrc[MRC_TYPE_VAR].buf =
fsp_get_var_nvs_data(gd->arch.hob_list,
&gd->arch.mrc[MRC_TYPE_VAR].len);
log_debug("normal %x, var %x\n",
gd->arch.mrc[MRC_TYPE_NORMAL].len,
gd->arch.mrc[MRC_TYPE_VAR].len);
#endif
} else {
#if CONFIG_IS_ENABLED(HANDOFF)
struct spl_handoff *ho = gd->spl_handoff;
if (!ho) {
debug("No SPL handoff found\n");
return -ESTRPIPE;
}
gd->ram_size = ho->ram_size;
handoff_load_dram_banks(ho);
#endif
ret = arch_fsps_preinit();
if (ret)
return log_msg_ret("fsp_s_preinit", ret);
}
return 0;
}
ulong board_get_usable_ram_top(ulong total_size)
{
#if CONFIG_IS_ENABLED(HANDOFF)
struct spl_handoff *ho = gd->spl_handoff;
return ho->arch.usable_ram_top;
#endif
return gd->ram_top;
}

View File

@ -0,0 +1,191 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google LLC
*/
#include <common.h>
#include <binman.h>
#include <binman_sym.h>
#include <cbfs.h>
#include <dm.h>
#include <init.h>
#include <spi.h>
#include <spl.h>
#include <spi_flash.h>
#include <asm/intel_pinctrl.h>
#include <dm/uclass-internal.h>
#include <asm/fsp2/fsp_internal.h>
int arch_cpu_init_dm(void)
{
struct udevice *dev;
ofnode node;
int ret;
/* Make sure pads are set up early in U-Boot */
if (spl_phase() != PHASE_BOARD_F)
return 0;
/* Probe all pinctrl devices to set up the pads */
ret = uclass_first_device_err(UCLASS_PINCTRL, &dev);
if (ret)
return log_msg_ret("no fsp pinctrl", ret);
node = ofnode_path("fsp");
if (!ofnode_valid(node))
return log_msg_ret("no fsp params", -EINVAL);
ret = pinctrl_config_pads_for_node(dev, node);
if (ret)
return log_msg_ret("pad config", ret);
return ret;
}
#if !defined(CONFIG_TPL_BUILD)
binman_sym_declare(ulong, intel_fsp_m, image_pos);
binman_sym_declare(ulong, intel_fsp_m, size);
/**
* get_cbfs_fsp() - Obtain the FSP by looking up in CBFS
*
* This looks up an FSP in a CBFS. It is used mostly for testing, when booting
* U-Boot from a hybrid image containing coreboot as the first-stage bootloader.
*
* The typical use for this feature is when building a Chrome OS image which
* includes coreboot in it. By adding U-Boot into the 'COREBOOT' CBFS as well,
* it is possible to make coreboot chain-load U-Boot. Thus the initial stages of
* the SoC init can be done by coreboot and the later stages by U-Boot. This is
* a convenient way to start the porting work. The jump to U-Boot can then be
* moved progressively earlier and earlier, until U-Boot takes over all the init
* and you have a native port.
*
* This function looks up a CBFS at a known location and reads the FSP-M from it
* so that U-Boot can init the memory.
*
* This function is not used in the normal boot but is kept here for future
* development.
*
* @type; Type to look up (only FSP_M supported at present)
* @map_base: Base memory address for mapped SPI
* @entry: Returns an entry containing the position of the FSP image
*/
static int get_cbfs_fsp(enum fsp_type_t type, ulong map_base,
struct binman_entry *entry)
{
/*
* Use a hard-coded position of CBFS in the ROM for now. It would be
* possible to read the position using the FMAP in the ROM, but since
* this code is only used for development, it doesn't seem worth it.
* Use the 'cbfstool <image> layout' command to get these values, e.g.:
* 'COREBOOT' (CBFS, size 1814528, offset 2117632).
*/
ulong cbfs_base = 0x205000;
ulong cbfs_size = 0x1bb000;
struct cbfs_priv *cbfs;
int ret;
ret = cbfs_init_mem(map_base + cbfs_base, cbfs_size, &cbfs);
if (ret)
return ret;
if (!ret) {
const struct cbfs_cachenode *node;
node = cbfs_find_file(cbfs, "fspm.bin");
if (!node)
return log_msg_ret("fspm node", -ENOENT);
entry->image_pos = (ulong)node->data;
entry->size = node->data_length;
}
return 0;
}
int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
bool use_spi_flash, struct udevice **devp,
struct fsp_header **hdrp, ulong *rom_offsetp)
{
ulong mask = CONFIG_ROM_SIZE - 1;
struct udevice *dev;
ulong rom_offset = 0;
uint map_size;
ulong map_base;
uint offset;
int ret;
/*
* Find the devices but don't probe them, since we don't want to
* auto-config PCI before silicon init runs
*/
ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev);
if (ret)
return log_msg_ret("Cannot get northbridge", ret);
if (!use_spi_flash) {
struct udevice *sf;
/* Just use the SPI driver to get the memory map */
ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf);
if (ret)
return log_msg_ret("Cannot get SPI flash", ret);
ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset);
if (ret)
return log_msg_ret("Could not get flash mmap", ret);
}
if (spl_phase() >= PHASE_BOARD_F) {
if (type != FSP_S)
return -EPROTONOSUPPORT;
ret = binman_entry_find("intel-fsp-s", entry);
if (ret)
return log_msg_ret("binman entry", ret);
if (!use_spi_flash)
rom_offset = (map_base & mask) - CONFIG_ROM_SIZE;
} else {
ret = -ENOENT;
if (false)
/*
* Support using a hybrid image build by coreboot. See
* the function comments for details
*/
ret = get_cbfs_fsp(type, map_base, entry);
if (ret) {
ulong mask = CONFIG_ROM_SIZE - 1;
if (type != FSP_M)
return -EPROTONOSUPPORT;
entry->image_pos = binman_sym(ulong, intel_fsp_m,
image_pos);
entry->size = binman_sym(ulong, intel_fsp_m, size);
if (entry->image_pos != BINMAN_SYM_MISSING) {
ret = 0;
if (use_spi_flash)
entry->image_pos &= mask;
else
entry->image_pos += (map_base & mask);
} else {
ret = -ENOENT;
}
}
}
if (ret)
return log_msg_ret("Cannot find FSP", ret);
entry->image_pos += rom_offset;
/*
* Account for the time taken to read memory-mapped SPI flash since in
* this case we don't use the SPI driver and BOOTSTAGE_ID_ACCUM_SPI.
*/
if (!use_spi_flash)
bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
ret = fsp_get_header(entry->image_pos, entry->size, use_spi_flash,
hdrp);
if (!use_spi_flash)
bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
if (ret)
return log_msg_ret("fsp_get_header", ret);
*devp = dev;
if (rom_offsetp)
*rom_offsetp = rom_offset;
return 0;
}
#endif

View File

@ -0,0 +1,97 @@
// SPDX-License-Identifier: Intel
/*
* Copyright (C) 2015-2016 Intel Corp.
* (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
* (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
* Mostly taken from coreboot fsp2_0/memory_init.c
*/
#include <common.h>
#include <binman.h>
#include <asm/mrccache.h>
#include <asm/fsp/fsp_infoheader.h>
#include <asm/fsp2/fsp_api.h>
#include <asm/fsp2/fsp_internal.h>
#include <asm/arch/fsp/fsp_configs.h>
#include <asm/arch/fsp/fsp_m_upd.h>
static int prepare_mrc_cache_type(enum mrc_type_t type,
struct mrc_data_container **cachep)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(type, NULL, &entry);
if (ret)
return ret;
cache = mrccache_find_current(&entry);
if (!cache)
return -ENOENT;
log_debug("MRC at %x, size %x\n", (uint)cache->data, cache->data_size);
*cachep = cache;
return 0;
}
int prepare_mrc_cache(struct fspm_upd *upd)
{
struct mrc_data_container *cache;
int ret;
ret = prepare_mrc_cache_type(MRC_TYPE_NORMAL, &cache);
if (ret)
return log_msg_ret("Cannot get normal cache", ret);
upd->arch.nvs_buffer_ptr = cache->data;
ret = prepare_mrc_cache_type(MRC_TYPE_VAR, &cache);
if (ret)
return log_msg_ret("Cannot get var cache", ret);
upd->config.variable_nvs_buffer_ptr = cache->data;
return 0;
}
int fsp_memory_init(bool s3wake, bool use_spi_flash)
{
struct fspm_upd upd, *fsp_upd;
fsp_memory_init_func func;
struct binman_entry entry;
struct fsp_header *hdr;
struct hob_header *hob;
struct udevice *dev;
int ret;
ret = fsp_locate_fsp(FSP_M, &entry, use_spi_flash, &dev, &hdr, NULL);
if (ret)
return log_msg_ret("locate FSP", ret);
debug("Found FSP_M at %x, size %x\n", hdr->img_base, hdr->img_size);
/* Copy over the default config */
fsp_upd = (struct fspm_upd *)(hdr->img_base + hdr->cfg_region_off);
if (fsp_upd->header.signature != FSPM_UPD_SIGNATURE)
return log_msg_ret("Bad UPD signature", -EPERM);
memcpy(&upd, fsp_upd, sizeof(upd));
ret = fspm_update_config(dev, &upd);
if (ret)
return log_msg_ret("Could not setup config", ret);
debug("SDRAM init...");
bootstage_start(BOOTSTATE_ID_ACCUM_FSP_M, "fsp-m");
func = (fsp_memory_init_func)(hdr->img_base + hdr->fsp_mem_init);
ret = func(&upd, &hob);
bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_M);
if (ret)
return log_msg_ret("SDRAM init fail\n", ret);
gd->arch.hob_list = hob;
debug("done\n");
ret = fspm_done(dev);
if (ret)
return log_msg_ret("fsm_done\n", ret);
return 0;
}

View File

@ -0,0 +1,54 @@
// SPDX-License-Identifier: Intel
/*
* Copyright (C) 2015-2016 Intel Corp.
* (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
*
* Mostly taken from coreboot fsp2_0/silicon_init.c
*/
#define LOG_CATEGORY UCLASS_NORTHBRIDGE
#include <common.h>
#include <binman.h>
#include <dm.h>
#include <asm/arch/fsp/fsp_configs.h>
#include <asm/arch/fsp/fsp_s_upd.h>
#include <asm/fsp/fsp_infoheader.h>
#include <asm/fsp2/fsp_internal.h>
int fsp_silicon_init(bool s3wake, bool use_spi_flash)
{
struct fsps_upd upd, *fsp_upd;
fsp_silicon_init_func func;
struct fsp_header *hdr;
struct binman_entry entry;
struct udevice *dev;
ulong rom_offset = 0;
int ret;
ret = fsp_locate_fsp(FSP_S, &entry, use_spi_flash, &dev, &hdr,
&rom_offset);
if (ret)
return log_msg_ret("locate FSP", ret);
gd->arch.fsp_s_hdr = hdr;
/* Copy over the default config */
fsp_upd = (struct fsps_upd *)(hdr->img_base + hdr->cfg_region_off);
if (fsp_upd->header.signature != FSPS_UPD_SIGNATURE)
return log_msg_ret("Bad UPD signature", -EPERM);
memcpy(&upd, fsp_upd, sizeof(upd));
ret = fsps_update_config(dev, rom_offset, &upd);
if (ret)
return log_msg_ret("Could not setup config", ret);
log_debug("Silicon init...");
bootstage_start(BOOTSTATE_ID_ACCUM_FSP_S, "fsp-s");
func = (fsp_silicon_init_func)(hdr->img_base + hdr->fsp_silicon_init);
ret = func(&upd);
bootstage_accum(BOOTSTATE_ID_ACCUM_FSP_S);
if (ret)
return log_msg_ret("Silicon init fail\n", ret);
log_debug("done\n");
return 0;
}

View File

@ -0,0 +1,131 @@
// SPDX-License-Identifier: Intel
/*
* Copyright 2019 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <dm.h>
#include <spi_flash.h>
#include <asm/fsp/fsp_support.h>
#include <asm/fsp2/fsp_internal.h>
/* The amount of the FSP header to probe to obtain what we need */
#define PROBE_BUF_SIZE 0x180
int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
struct fsp_header **fspp)
{
static efi_guid_t guid = FSP_HEADER_GUID;
struct fv_ext_header *exhdr;
struct fsp_header *fsp;
struct ffs_file_header *file_hdr;
struct fv_header *fv;
struct raw_section *raw;
void *ptr, *base;
u8 buf[PROBE_BUF_SIZE];
struct udevice *dev;
int ret;
/*
* There are quite a very steps to work through all the headers in this
* file and the structs have similar names. Turn on debugging if needed
* to understand what is going wrong.
*
* You are in a maze of twisty little headers all alike.
*/
debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
if (use_spi_flash) {
ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
if (ret)
return log_msg_ret("Cannot find flash device", ret);
ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
if (ret)
return log_msg_ret("Cannot read flash", ret);
} else {
memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
}
/* Initalise the FSP base */
ptr = buf;
fv = ptr;
/* Check the FV signature, _FVH */
debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
if (fv->sign != EFI_FVH_SIGNATURE)
return log_msg_ret("Base FV signature", -EINVAL);
/* Go to the end of the FV header and align the address */
debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
ptr += fv->ext_hdr_off;
exhdr = ptr;
ptr += ALIGN(exhdr->ext_hdr_size, 8);
debug("ptr=%x\n", ptr - (void *)buf);
/* Check the FFS GUID */
file_hdr = ptr;
if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
return log_msg_ret("Base FFS GUID", -ENXIO);
/* Add the FFS header size to find the raw section header */
ptr = file_hdr + 1;
raw = ptr;
debug("raw->type = %x\n", raw->type);
if (raw->type != EFI_SECTION_RAW)
return log_msg_ret("Section type not RAW", -ENOEXEC);
/* Add the raw section header size to find the FSP header */
ptr = raw + 1;
fsp = ptr;
/* Check the FSPH header */
debug("fsp %x\n", (uint)fsp);
if (fsp->sign != EFI_FSPH_SIGNATURE)
return log_msg_ret("Base FSPH signature", -EACCES);
base = (void *)fsp->img_base;
debug("Image base %x\n", (uint)base);
debug("Image addr %x\n", (uint)fsp->fsp_mem_init);
if (use_spi_flash) {
ret = spi_flash_read_dm(dev, offset, size, base);
if (ret)
return log_msg_ret("Could not read FPS-M", ret);
} else {
memcpy(base, (void *)offset, size);
}
ptr = base + (ptr - (void *)buf);
*fspp = ptr;
return 0;
}
u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
{
fsp_notify_f notify;
struct fsp_notify_params params;
struct fsp_notify_params *params_ptr;
u32 status;
if (!fsp_hdr)
fsp_hdr = gd->arch.fsp_s_hdr;
if (!fsp_hdr)
return log_msg_ret("no FSP", -ENOENT);
notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
params.phase = phase;
params_ptr = &params;
/*
* Use ASM code to ensure correct parameter is on the stack for
* FspNotify as U-Boot is using different ABI from FSP
*/
asm volatile (
"pushl %1;" /* push notify phase */
"call *%%eax;" /* call FspNotify */
"addl $4, %%esp;" /* clean up the stack */
: "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
);
return status;
}

View File

@ -14,6 +14,8 @@
#include <spi.h>
#include <spi_flash.h>
#include <asm/mrccache.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
DECLARE_GLOBAL_DATA_PTR;
@ -80,21 +82,31 @@ struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
/**
* find_next_mrc_cache() - get next cache entry
*
* This moves to the next cache entry in the region, making sure it has enough
* space to hold data of size @data_size.
*
* @entry: MRC cache flash area
* @cache: Entry to start from
* @data_size: Required data size of the new entry. Note that we assume that
* all cache entries are the same size
*
* @return next cache entry if found, NULL if we got to the end
*/
static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
struct mrc_data_container *cache)
struct mrc_data_container *prev, int data_size)
{
struct mrc_data_container *cache;
ulong base_addr, end_addr;
base_addr = entry->base + entry->offset;
end_addr = base_addr + entry->length;
cache = next_mrc_block(cache);
if ((ulong)cache >= end_addr) {
/*
* We assume that all cache entries are the same size, but let's use
* data_size here for clarity.
*/
cache = next_mrc_block(prev);
if ((ulong)cache + mrc_block_size(data_size) > end_addr) {
/* Crossed the boundary */
cache = NULL;
debug("%s: no available entries found\n", __func__);
@ -106,8 +118,20 @@ static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
return cache;
}
int mrccache_update(struct udevice *sf, struct mrc_region *entry,
struct mrc_data_container *cur)
/**
* mrccache_update() - update the MRC cache with a new record
*
* This writes a new record to the end of the MRC cache region. If the new
* record is the same as the latest record then the write is skipped
*
* @sf: SPI flash to write to
* @entry: Position and size of MRC cache in SPI flash
* @cur: Record to write
* @return 0 if updated, -EEXIST if the record is the same as the latest
* record, -EINVAL if the record is not valid, other error if SPI write failed
*/
static int mrccache_update(struct udevice *sf, struct mrc_region *entry,
struct mrc_data_container *cur)
{
struct mrc_data_container *cache;
ulong offset;
@ -131,7 +155,7 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
/* Move to the next block, which will be the first unused block */
if (cache)
cache = find_next_mrc_cache(entry, cache);
cache = find_next_mrc_cache(entry, cache, cur->data_size);
/*
* If we have got to the end, erase the entire mrc-cache area and start
@ -156,82 +180,136 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
cur);
if (ret) {
debug("Failed to write to SPI flash\n");
return ret;
return log_msg_ret("Cannot update mrccache", ret);
}
return 0;
}
static void mrccache_setup(void *data)
static void mrccache_setup(struct mrc_output *mrc, void *data)
{
struct mrc_data_container *cache = data;
u16 checksum;
cache->signature = MRC_DATA_SIGNATURE;
cache->data_size = gd->arch.mrc_output_len;
checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
cache->data_size = mrc->len;
checksum = compute_ip_checksum(mrc->buf, cache->data_size);
debug("Saving %d bytes for MRC output data, checksum %04x\n",
cache->data_size, checksum);
cache->checksum = checksum;
cache->reserved = 0;
memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
memcpy(cache->data, mrc->buf, cache->data_size);
/* gd->arch.mrc_output now points to the container */
gd->arch.mrc_output = (char *)cache;
mrc->cache = cache;
}
int mrccache_reserve(void)
{
if (!gd->arch.mrc_output_len)
return 0;
int i;
/* adjust stack pointer to store pure cache data plus the header */
gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
mrccache_setup((void *)gd->start_addr_sp);
for (i = 0; i < MRC_TYPE_COUNT; i++) {
struct mrc_output *mrc = &gd->arch.mrc[i];
gd->start_addr_sp &= ~0xf;
if (!mrc->len)
continue;
/* adjust stack pointer to store pure cache data plus header */
gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
mrccache_setup(mrc, (void *)gd->start_addr_sp);
gd->start_addr_sp &= ~0xf;
}
return 0;
}
int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
struct mrc_region *entry)
{
const void *blob = gd->fdt_blob;
int node, mrc_node;
struct udevice *dev;
ofnode mrc_node;
ulong map_base;
uint map_size;
uint offset;
u32 reg[2];
int ret;
/* Find the flash chip within the SPI controller node */
node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
if (node < 0) {
debug("%s: Cannot find SPI flash\n", __func__);
return -ENOENT;
/*
* Find the flash chip within the SPI controller node. Avoid probing
* the device here since it may put it into a strange state where the
* memory map cannot be read.
*/
ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
if (ret)
return log_msg_ret("Cannot find SPI flash\n", ret);
ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
if (!ret) {
entry->base = map_base;
} else {
ret = dev_read_u32_array(dev, "memory-map", reg, 2);
if (ret)
return log_msg_ret("Cannot find memory map\n", ret);
entry->base = reg[0];
}
if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) {
debug("%s: Cannot find memory map\n", __func__);
return -EINVAL;
}
entry->base = reg[0];
/* Find the place where we put the MRC cache */
mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
if (mrc_node < 0) {
debug("%s: Cannot find node\n", __func__);
return -EPERM;
}
mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
"rw-mrc-cache" : "rw-var-mrc-cache");
if (!ofnode_valid(mrc_node))
return log_msg_ret("Cannot find node", -EPERM);
if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) {
debug("%s: Cannot find address\n", __func__);
return -EINVAL;
}
ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
if (ret)
return log_msg_ret("Cannot find address", ret);
entry->offset = reg[0];
entry->length = reg[1];
if (devp) {
ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
devp);
debug("ret = %d\n", ret);
if (devp)
*devp = dev;
debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
type, dev->name, entry->offset, entry->length, entry->base);
return 0;
}
static int mrccache_save_type(enum mrc_type_t type)
{
struct mrc_data_container *cache;
struct mrc_output *mrc;
struct mrc_region entry;
struct udevice *sf;
int ret;
mrc = &gd->arch.mrc[type];
if (!mrc->len)
return 0;
log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
mrc->len, type);
ret = mrccache_get_region(type, &sf, &entry);
if (ret)
return log_msg_ret("Cannot get region", ret);
ret = device_probe(sf);
if (ret)
return log_msg_ret("Cannot probe device", ret);
cache = mrc->cache;
ret = mrccache_update(sf, &entry, cache);
if (!ret)
debug("Saved MRC data with checksum %04x\n", cache->checksum);
else if (ret == -EEXIST)
debug("MRC data is the same as last time, skipping save\n");
return 0;
}
int mrccache_save(void)
{
int i;
for (i = 0; i < MRC_TYPE_COUNT; i++) {
int ret;
ret = mrccache_save_type(i);
if (ret)
return ret;
}
@ -239,47 +317,21 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
return 0;
}
int mrccache_save(void)
{
struct mrc_data_container *data;
struct mrc_region entry;
struct udevice *sf;
int ret;
if (!gd->arch.mrc_output_len)
return 0;
debug("Saving %d bytes of MRC output data to SPI flash\n",
gd->arch.mrc_output_len);
ret = mrccache_get_region(&sf, &entry);
if (ret)
goto err_entry;
data = (struct mrc_data_container *)gd->arch.mrc_output;
ret = mrccache_update(sf, &entry, data);
if (!ret) {
debug("Saved MRC data with checksum %04x\n", data->checksum);
} else if (ret == -EEXIST) {
debug("MRC data is the same as last time, skipping save\n");
ret = 0;
}
err_entry:
if (ret)
debug("%s: Failed: %d\n", __func__, ret);
return ret;
}
int mrccache_spl_save(void)
{
void *data;
int size;
int i;
size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE;
data = malloc(size);
if (!data)
return log_msg_ret("Allocate MRC cache block", -ENOMEM);
mrccache_setup(data);
gd->arch.mrc_output = data;
for (i = 0; i < MRC_TYPE_COUNT; i++) {
struct mrc_output *mrc = &gd->arch.mrc[i];
void *data;
int size;
size = mrc->len + MRC_DATA_HEADER_SIZE;
data = malloc(size);
if (!data)
return log_msg_ret("Allocate MRC cache block", -ENOMEM);
mrccache_setup(mrc, data);
}
return mrccache_save();
}

View File

@ -10,6 +10,8 @@
#include <asm/pci.h>
#include <asm/pirq_routing.h>
DECLARE_GLOBAL_DATA_PTR;
static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap,
bool irq_already_routed[])
{
@ -131,3 +133,11 @@ u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt)
return addr + rt->size;
}
ulong write_pirq_routing_table(ulong addr)
{
if (!gd->arch.pirq_routing_table)
return addr;
return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table);
}

View File

@ -50,7 +50,7 @@ int board_early_init_f(void)
return 0;
}
#if IS_ENABLED(CONFIG_DM_GPIO)
#if CONFIG_IS_ENABLED(DM_GPIO)
static void board_gpio_init(void)
{
/* TODO */

View File

@ -54,7 +54,7 @@ int board_early_init_f(void)
return 0;
}
#if IS_ENABLED(CONFIG_DM_GPIO)
#if CONFIG_IS_ENABLED(DM_GPIO)
static void board_gpio_init(void)
{
struct gpio_desc desc;

Some files were not shown because too many files have changed in this diff Show More