[U-Boot] [PATCH 101/126] x86: Use fsp command with FSP1

The current 'fsp' command only works with FSP1. Update it to avoid trying to build it with FSP2.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 144b1cf5abe..c50ddccef57 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -3,4 +3,4 @@ obj-y += mtrr.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o obj-$(CONFIG_USE_HOB) += hob.o -obj-$(CONFIG_HAVE_FSP) += fsp.o +obj-$(CONFIG_FSP_VERSION1) += fsp.o

Include the IFWI section and the FSP-M binary. The FSP-T binary is not currently used, as CAR is set up manually.
Also drop the FSP binary as this relates only to FSP1.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 35129d0510b..189be2196cb 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -104,12 +104,39 @@ 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; + }; +#endif #ifdef CONFIG_HAVE_CMC intel-cmc { filename = CONFIG_CMC_FILE;

Hi Simon,
On Wed, Sep 25, 2019 at 11:02 PM Simon Glass sjg@chromium.org wrote:
Include the IFWI section and the FSP-M binary. The FSP-T binary is not currently used, as CAR is set up manually.
Also drop the FSP binary as this relates only to FSP1.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/u-boot.dtsi | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 35129d0510b..189be2196cb 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -104,12 +104,39 @@ 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;
nits: can we rename this to CONFIG_IFWI_FILE? for consistency
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;
};
What about FSP-S?
+#endif #ifdef CONFIG_HAVE_CMC intel-cmc { filename = CONFIG_CMC_FILE; --
Regards, Bin

The existing work-around for positioning U-Boot in the ROM when it actually runs from RAM still exists and there is not obvious way to change this.
Add a proper Kconfig option to handle this case. This also adds a new bool property to indicate whether CONFIG_SYS_TEXT_BASE exists.
Signed-off-by: Simon Glass sjg@chromium.org ---
Kconfig | 9 ++++++--- arch/x86/Kconfig | 5 +++++ arch/x86/dts/u-boot.dtsi | 18 +++--------------- configs/chromebook_samus_tpl_defconfig | 1 + 4 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/Kconfig b/Kconfig index 1f0904f7045..f772d4fbe9f 100644 --- a/Kconfig +++ b/Kconfig @@ -529,9 +529,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 HAS_SYS_TEXT_BASE + bool depends on !NIOS2 && !XTENSA depends on !EFI_APP + default y + +config SYS_TEXT_BASE + depends on HAS_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 @@ -540,8 +545,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" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fce3c1d92a3..02c116caeb7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -891,4 +891,9 @@ config CACHE_QOS_SIZE_PER_BIT depends on INTEL_CAR_CQOS default 0x20000 # 128 KB
+config X86_OFFSET_U_BOOT + hex "Offset of U-Boot in ROM image" + depends on HAS_SYS_TEXT_BASE + default SYS_TEXT_BASE + endmenu diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 189be2196cb..f33f276b90d 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -54,7 +54,7 @@ u-boot-spl-dtb { }; u-boot { - offset = <CONFIG_SYS_TEXT_BASE>; + offset = <CONFIG_X86_OFFSET_U_BOOT>; }; #elif defined(CONFIG_SPL) u-boot-spl-with-ucode-ptr { @@ -64,23 +64,11 @@ 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 u-boot-with-ucode-ptr { - offset = <CONFIG_SYS_TEXT_BASE>; + offset = <CONFIG_X86_OFFSET_U_BOOT>; }; #endif #ifdef CONFIG_HAVE_MICROCODE diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig index 28f23cfe125..c7f125eaa40 100644 --- a/configs/chromebook_samus_tpl_defconfig +++ b/configs/chromebook_samus_tpl_defconfig @@ -13,6 +13,7 @@ CONFIG_HAVE_REFCODE=y CONFIG_SMP=y CONFIG_HAVE_VGA_BIOS=y CONFIG_SPL_TEXT_BASE=0xffe70000 +CONFIG_X86_OFFSET_U_BOOT=0xfff00000 CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_SHOW_BOOT_PROGRESS=y

For apollolake SPL is run from CAR (cache-as-RAM) which is in a different location from where SPL must be placed in ROM. In other words, although SPL runs before SDRAM is set up, it is not execute-in-place (XIP).
Add a Kconfig option for the ROM position.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Kconfig | 5 +++++ arch/x86/dts/u-boot.dtsi | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 02c116caeb7..9d01801ff13 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -896,4 +896,9 @@ config X86_OFFSET_U_BOOT depends on HAS_SYS_TEXT_BASE default SYS_TEXT_BASE
+config X86_OFFSET_SPL + hex "Offset of SPL in ROM image" + depends on X86 + default SPL_TEXT_BASE + endmenu diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index f33f276b90d..8fc5146f26c 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -49,7 +49,7 @@ u-boot-tpl-dtb { }; u-boot-spl { - offset = <CONFIG_SPL_TEXT_BASE>; + offset = <CONFIG_X86_OFFSET_SPL>; }; u-boot-spl-dtb { }; @@ -58,7 +58,7 @@ }; #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";

At present this produces a 16-byte file. It is intended to start 16 bytes before the end of ROM and pads with zeroes to readh the end.
But binman sometimes wants to add an image-header at the very end of ROM. Furthermore binman automatically pads the data if it is finishes early.
Drop the padding in resetvec and let binman handle it.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/resetvec.S | 3 --- 1 file changed, 3 deletions(-)
diff --git a/arch/x86/cpu/resetvec.S b/arch/x86/cpu/resetvec.S index a52225d5ee9..cf972738b31 100644 --- a/arch/x86/cpu/resetvec.S +++ b/arch/x86/cpu/resetvec.S @@ -16,6 +16,3 @@ reset_vector: cli cld jmp start16 - - .org 0xf - nop

On Wed, Sep 25, 2019 at 11:02 PM Simon Glass sjg@chromium.org wrote:
At present this produces a 16-byte file. It is intended to start 16 bytes before the end of ROM and pads with zeroes to readh the end.
But binman sometimes wants to add an image-header at the very end of ROM. Furthermore binman automatically pads the data if it is finishes early.
Drop the padding in resetvec and let binman handle it.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/resetvec.S | 3 --- 1 file changed, 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Thu, Oct 10, 2019 at 3:12 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 11:02 PM Simon Glass sjg@chromium.org wrote:
At present this produces a 16-byte file. It is intended to start 16 bytes before the end of ROM and pads with zeroes to readh the end.
But binman sometimes wants to add an image-header at the very end of ROM. Furthermore binman automatically pads the data if it is finishes early.
Drop the padding in resetvec and let binman handle it.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/resetvec.S | 3 --- 1 file changed, 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

Add these entries to the ROM so that we can list the contents of an image with 'binman ls'. The image-header is not essential but does speed up access.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 8fc5146f26c..f2fb4c2abaa 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -125,6 +125,8 @@ filename = CONFIG_FSP_FILE_M; }; #endif + fdtmap { + }; #ifdef CONFIG_HAVE_CMC intel-cmc { filename = CONFIG_CMC_FILE; @@ -170,5 +172,8 @@ offset = <CONFIG_RESET_VEC_LOC>; }; #endif + image-header { + location = "end"; + }; }; #endif

At present if SPL sets up the microcode then it is still included in U-Boot as well. This is wasteful as microcode is large. Adjust the logic in the image to prevent this.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index f2fb4c2abaa..d9a4ca1184e 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -67,9 +67,16 @@ 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_X86_OFFSET_U_BOOT>; }; +# endif #endif #ifdef CONFIG_HAVE_MICROCODE u-boot-dtb-with-ucode {

Add some fixed IO and mmap addresses for use in the device tree and with some early-init code.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/arch-apollolake/iomap.h | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 arch/x86/include/asm/arch-apollolake/iomap.h
diff --git a/arch/x86/include/asm/arch-apollolake/iomap.h b/arch/x86/include/asm/arch-apollolake/iomap.h new file mode 100644 index 00000000000..200c76a8eef --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/iomap.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Take from coreboot project file of the same name + */ + +#ifndef __ARCH_IOMAP_H +#define __ARCH_IOMAP_H + +#define TCO_BASE_ADDRESS (ACPI_BASE_ADDRESS + 0x60) +#define TCO_BASE_SIZE 0x20 + +#define R_ACPI_PM1_TMR 0x8 + +/* Put p2sb at 0xd0000000 in TPL */ +#define IOMAP_P2SB_BAR 0xd0000000 + +#define IOMAP_SPI_BASE 0xfe010000 +/* + * 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

Add a driver for the apollolake SoC. It supports the basic operations and can use device tree or of-platdata.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 5 + arch/x86/cpu/apollolake/pmc.c | 216 +++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/pm.h | 19 ++ drivers/power/power_mgr/power-mgr-uclass.c | 51 +++++ 4 files changed, 291 insertions(+) create mode 100644 arch/x86/cpu/apollolake/Makefile create mode 100644 arch/x86/cpu/apollolake/pmc.c create mode 100644 arch/x86/include/asm/arch-apollolake/pm.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile new file mode 100644 index 00000000000..5d98a5a6db2 --- /dev/null +++ b/arch/x86/cpu/apollolake/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2016 Google, Inc + +obj-y += pmc.o diff --git a/arch/x86/cpu/apollolake/pmc.c b/arch/x86/cpu/apollolake/pmc.c new file mode 100644 index 00000000000..4d27bb69ea5 --- /dev/null +++ b/arch/x86/cpu/apollolake/pmc.c @@ -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_POWER_MGR + +#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/power_mgr.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 power_mgr_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 power_mgr_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 power_mgr_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 power_mgr_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 power_mgr_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_x86_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_x86_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 power_mgr_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 power_mgr_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_POWER_MGR, + .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), +}; diff --git a/arch/x86/include/asm/arch-apollolake/pm.h b/arch/x86/include/asm/arch-apollolake/pm.h new file mode 100644 index 00000000000..8226ee775e1 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/pm.h @@ -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 diff --git a/drivers/power/power_mgr/power-mgr-uclass.c b/drivers/power/power_mgr/power-mgr-uclass.c index 0d73caf8cf6..40d93c13cad 100644 --- a/drivers/power/power_mgr/power-mgr-uclass.c +++ b/drivers/power/power_mgr/power-mgr-uclass.c @@ -37,6 +37,57 @@ enum { TCO1_CNT_HLT = 1 << 11, };
+#ifdef CONFIG_X86 +static int gpe0_shift(struct power_mgr_upriv *upriv, int regnum) +{ + return upriv->gpe0_dwx_shift_base + regnum * 4; +} + +int pmc_gpe_init(struct udevice *dev) +{ + struct power_mgr_upriv *upriv = dev_get_uclass_priv(dev); + struct udevice *itss; + u32 *dw; + u32 gpio_cfg_mask; + u32 gpio_cfg; + int ret, i; + u32 mask; + + dw = upriv->gpe0_dw; + mask = upriv->gpe0_dwx_mask; + gpio_cfg_mask = 0; + for (i = 0; i < upriv->gpe0_count; i++) { + gpio_cfg_mask |= mask << gpe0_shift(upriv, i); + if (dw[i] & mask) + return log_msg_ret("Base GPE0 value", -EINVAL); + } + + /* + * Route the GPIOs to the GPE0 block. Determine that all values + * are different and if they aren't, use the reset values. + */ + if (dw[0] == dw[1] || dw[1] == dw[2]) { + log_info("PMC: Using default GPE route"); + gpio_cfg = readl(upriv->gpe_cfg); + for (i = 0; i < upriv->gpe0_count; i++) + dw[i] = gpio_cfg >> gpe0_shift(upriv, i); + } else { + gpio_cfg = 0; + for (i = 0; i < upriv->gpe0_count; i++) + gpio_cfg |= dw[i] << gpe0_shift(upriv, i); + clrsetbits_le32(upriv->gpe_cfg, gpio_cfg_mask, gpio_cfg); + } + + /* Set the routes in the GPIO communities as well */ + ret = uclass_first_device_err(UCLASS_ITSS, &itss); + if (ret) + return log_msg_ret("Cannot find itss", ret); + gpio_route_gpe(itss, dw[0], dw[1], dw[2]); + + return 0; +} +#endif /* CONFIG_X86 */ + static void pmc_fill_pm_reg_info(struct udevice *dev) { struct power_mgr_upriv *upriv = dev_get_uclass_priv(dev);

Add a driver for the apollolake UART. It uses the standard ns16550 device but also sets up the input clock with LPSS and supports configuration via of-platdata.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/uart.c | 157 ++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/uart.h | 17 +++ 3 files changed, 175 insertions(+) create mode 100644 arch/x86/cpu/apollolake/uart.c create mode 100644 arch/x86/include/asm/arch-apollolake/uart.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 5d98a5a6db2..af7c4396619 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -3,3 +3,4 @@ # Copyright (c) 2016 Google, Inc
obj-y += pmc.o +obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/uart.c b/arch/x86/cpu/apollolake/uart.c new file mode 100644 index 00000000000..d4ce8312bcc --- /dev/null +++ b/arch/x86/cpu/apollolake/uart.c @@ -0,0 +1,157 @@ +// 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> + +/* 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, + + LPSS_RESET_CTL_REG = 0x204, + + /* These set the UART input clock speed */ + LPSS_UART_CLK_M_VAL = 0x25a, + LPSS_UART_CLK_N_VAL = 0x7fff, +}; + +/* + * 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) + */ +#define LPSS_CNT_RST_RELEASE 3 + +/* Take controller out of reset */ +static void lpss_reset_release(void *regs) +{ + writel(LPSS_CNT_RST_RELEASE, regs + LPSS_RESET_CTL_REG); +} + +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) +{ + struct ns16550_platdata *plat; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_intel_apl_ns16550 *dtplat = dev_get_platdata(dev); + + /* + * 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_x86_ofplat_get_devfn(dtplat->reg[0]); + dev->platdata = plat; +#else + int ret; + + ret = ns16550_serial_ofdata_to_platdata(dev); + if (ret) + return ret; + if (!CONFIG_IS_ENABLED(OF_TRANSLATE)) { + /* + * Without address translation we cannot get correct PCI + * address, so just read the BAR manually. + */ + plat = dev_get_platdata(dev); + plat->base = dm_pci_read_bar32(dev, 0); + } +#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, +}; diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h new file mode 100644 index 00000000000..521316d0a93 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/uart.h @@ -0,0 +1,17 @@ +/* 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 + * + * The UART won't actually work unless the GPIO settings are correct and the + * signals actually exit the SoC. See init_for_uart() for that. + */ +int apl_uart_init(pci_dev_t bdf, ulong base); + +#endif

Add a driver for the apollolake GPIOs. It also handles pinctrl since this is not very well separated on x86.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/gpio.c | 742 ++++++++++++++++++ arch/x86/include/asm/arch-apollolake/gpio.h | 156 ++++ .../include/asm/arch-apollolake/gpio_apl.h | 491 ++++++++++++ .../include/asm/arch-apollolake/gpio_defs.h | 398 ++++++++++ 5 files changed, 1788 insertions(+) create mode 100644 arch/x86/cpu/apollolake/gpio.c create mode 100644 arch/x86/include/asm/arch-apollolake/gpio.h create mode 100644 arch/x86/include/asm/arch-apollolake/gpio_apl.h create mode 100644 arch/x86/include/asm/arch-apollolake/gpio_defs.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index af7c4396619..f985018228a 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,5 +2,6 @@ # # Copyright (c) 2016 Google, Inc
+obj-y += gpio.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/gpio.c b/arch/x86/cpu/apollolake/gpio.c new file mode 100644 index 00000000000..e16c06a0e2d --- /dev/null +++ b/arch/x86/cpu/apollolake/gpio.c @@ -0,0 +1,742 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Intel Corp. + * Copyright 2019 Google LLC + * + * Taken partly from coreboot gpio.c + */ + +#define LOG_CATEGORY UCLASS_GPIO + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> +#include <itss.h> +#include <p2sb.h> +#include <spl.h> +#include <asm-generic/gpio.h> +#include <asm/arch/gpio.h> +#include <asm/arch/gpio_defs.h> +#include <asm/arch/itss.h> + +/** + * struct apl_gpio_platdata - platform data for each device + * + * @dtplat: of-platdata data from C struct + * @num_cfgs: Number of configuration words for each pad + * @early_pads: Early pad data to set up, each (pad, cfg0, cfg1) + * @early_pads_count: Number of pads to process + * @comm: Pad community for this device + */ +struct apl_gpio_platdata { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + /* Put this first since driver model will copy the data here */ + struct dtd_intel_apl_gpio dtplat; +#endif + int num_cfgs; + u32 *early_pads; + int early_pads_count; + const struct pad_community *comm; +}; + +/** struct apl_gpio_priv - private data for each device + * + * @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 apl_gpio_priv { + struct udevice *itss; + bool itss_pol_cfg; +}; + +#define GPIO_DWx_SIZE(x) (sizeof(u32) * (x)) +#define PAD_CFG_OFFSET(x, dw_num) ((x) + GPIO_DWx_SIZE(dw_num)) +#define PAD_CFG0_OFFSET(x) PAD_CFG_OFFSET(x, 0) +#define PAD_CFG1_OFFSET(x) PAD_CFG_OFFSET(x, 1) + +#define MISCCFG_GPE0_DW0_SHIFT 8 +#define MISCCFG_GPE0_DW0_MASK (0xf << MISCCFG_GPE0_DW0_SHIFT) +#define MISCCFG_GPE0_DW1_SHIFT 12 +#define MISCCFG_GPE0_DW1_MASK (0xf << MISCCFG_GPE0_DW1_SHIFT) +#define MISCCFG_GPE0_DW2_SHIFT 16 +#define MISCCFG_GPE0_DW2_MASK (0xf << MISCCFG_GPE0_DW2_SHIFT) + +#define GPI_SMI_STS_OFFSET(comm, group) ((comm)->gpi_smi_sts_reg_0 + \ + ((group) * sizeof(u32))) +#define GPI_SMI_EN_OFFSET(comm, group) ((comm)->gpi_smi_en_reg_0 + \ + ((group) * sizeof(u32))) + +static const struct reset_mapping rst_map[] = { + { .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 }, + { .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 }, +}; + +static const struct pad_group apl_community_n_groups[] = { + INTEL_GPP(N_OFFSET, N_OFFSET, GPIO_31), /* NORTH 0 */ + INTEL_GPP(N_OFFSET, GPIO_32, JTAG_TRST_B), /* NORTH 1 */ + INTEL_GPP(N_OFFSET, JTAG_TMS, SVID0_CLK), /* NORTH 2 */ +}; + +static const struct pad_group apl_community_w_groups[] = { + INTEL_GPP(W_OFFSET, W_OFFSET, OSC_CLK_OUT_1),/* WEST 0 */ + INTEL_GPP(W_OFFSET, OSC_CLK_OUT_2, SUSPWRDNACK),/* WEST 1 */ +}; + +static const struct pad_group apl_community_sw_groups[] = { + INTEL_GPP(SW_OFFSET, SW_OFFSET, SMB_ALERTB), /* SOUTHWEST 0 */ + INTEL_GPP(SW_OFFSET, SMB_CLK, LPC_FRAMEB), /* SOUTHWEST 1 */ +}; + +static const struct pad_group apl_community_nw_groups[] = { + INTEL_GPP(NW_OFFSET, NW_OFFSET, PROCHOT_B), /* NORTHWEST 0 */ + INTEL_GPP(NW_OFFSET, PMIC_I2C_SCL, GPIO_106),/* NORTHWEST 1 */ + INTEL_GPP(NW_OFFSET, GPIO_109, GPIO_123), /* NORTHWEST 2 */ +}; + +/* TODO(sjg@chromium.org): Consider moving this to device tree */ +static const struct pad_community apl_gpio_communities[] = { + { + .port = PID_GPIO_N, + .first_pad = N_OFFSET, + .last_pad = SVID0_CLK, + .num_gpi_regs = NUM_N_GPI_REGS, + .gpi_status_offset = NUM_NW_GPI_REGS + NUM_W_GPI_REGS + + NUM_SW_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPIO_GPE_N", + .acpi_path = "\_SB.GPO0", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = apl_community_n_groups, + .num_groups = ARRAY_SIZE(apl_community_n_groups), + }, { + .port = PID_GPIO_NW, + .first_pad = NW_OFFSET, + .last_pad = GPIO_123, + .num_gpi_regs = NUM_NW_GPI_REGS, + .gpi_status_offset = NUM_W_GPI_REGS + NUM_SW_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPIO_GPE_NW", + .acpi_path = "\_SB.GPO1", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = apl_community_nw_groups, + .num_groups = ARRAY_SIZE(apl_community_nw_groups), + }, { + .port = PID_GPIO_W, + .first_pad = W_OFFSET, + .last_pad = SUSPWRDNACK, + .num_gpi_regs = NUM_W_GPI_REGS, + .gpi_status_offset = NUM_SW_GPI_REGS, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPIO_GPE_W", + .acpi_path = "\_SB.GPO2", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = apl_community_w_groups, + .num_groups = ARRAY_SIZE(apl_community_w_groups), + }, { + .port = PID_GPIO_SW, + .first_pad = SW_OFFSET, + .last_pad = LPC_FRAMEB, + .num_gpi_regs = NUM_SW_GPI_REGS, + .gpi_status_offset = 0, + .pad_cfg_base = PAD_CFG_BASE, + .host_own_reg_0 = HOSTSW_OWN_REG_0, + .gpi_int_sts_reg_0 = GPI_INT_STS_0, + .gpi_int_en_reg_0 = GPI_INT_EN_0, + .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, + .gpi_smi_en_reg_0 = GPI_SMI_EN_0, + .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, + .name = "GPIO_GPE_SW", + .acpi_path = "\_SB.GPO3", + .reset_map = rst_map, + .num_reset_vals = ARRAY_SIZE(rst_map), + .groups = apl_community_sw_groups, + .num_groups = ARRAY_SIZE(apl_community_sw_groups), + }, +}; + +static size_t relative_pad_in_comm(const struct pad_community *comm, + uint gpio) +{ + return gpio - comm->first_pad; +} + +/* find the group within the community that the pad is a part of */ +static int gpio_group_index(const struct pad_community *comm, uint relative_pad) +{ + int i; + + if (!comm->groups) + return -ESPIPE; + + /* find the base pad number for this pad's group */ + for (i = 0; i < comm->num_groups; i++) { + if (relative_pad >= comm->groups[i].first_pad && + relative_pad < comm->groups[i].first_pad + + comm->groups[i].size) + return i; + } + + return -ENOENT; +} + +static int gpio_group_index_scaled(const struct pad_community *comm, + uint relative_pad, size_t scale) +{ + int ret; + + ret = gpio_group_index(comm, relative_pad); + if (ret < 0) + return ret; + + return ret * scale; +} + +static int gpio_within_group(const struct pad_community *comm, + uint relative_pad) +{ + int ret; + + ret = gpio_group_index(comm, relative_pad); + if (ret < 0) + return ret; + + return relative_pad - comm->groups[ret].first_pad; +} + +static u32 gpio_bitmask_within_group(const struct pad_community *comm, + uint relative_pad) +{ + return 1U << gpio_within_group(comm, relative_pad); +} + +/** + * gpio_get_device() - Find the device for a particular pad + * + * Each GPIO device is attached to one community and this supports a number of + * GPIO pins. This function finds the device which controls a particular pad. + * + * @pad: Pad to check + * @devp: Returns the device for that pad + * @return 0 if OK, -ENOTBLK if no device was found for the given pin + */ +static int gpio_get_device(uint pad, struct udevice **devp) +{ + struct udevice *dev; + + /* + * We have to probe each one of these since the community link is only + * attached in apl_gpio_ofdata_to_platdata(). + */ + uclass_foreach_dev_probe(UCLASS_GPIO, dev) { + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + const struct pad_community *comm = plat->comm; + + if (pad >= comm->first_pad && pad <= comm->last_pad) { + *devp = dev; + return 0; + } + } + printf("pad %d not found\n", pad); + + return -ENOTBLK; +} + +static int gpio_configure_owner(struct udevice *dev, + const struct pad_config *cfg, + const struct pad_community *comm) +{ + u32 hostsw_own; + u16 hostsw_own_offset; + int pin; + int ret; + + pin = relative_pad_in_comm(comm, cfg->pad); + + /* Based on the gpio pin number configure the corresponding bit in + * HOSTSW_OWN register. Value of 0x1 indicates GPIO Driver onwership. + */ + hostsw_own_offset = comm->host_own_reg_0; + ret = gpio_group_index_scaled(comm, pin, sizeof(u32)); + if (ret < 0) + return ret; + hostsw_own_offset += ret; + + hostsw_own = pcr_read32(dev, hostsw_own_offset); + + /* The 4th bit in pad_config 1 (RO) is used to indicate if the pad + * needs GPIO driver ownership. Set the bit if GPIO driver ownership + * requested, otherwise clear the bit. + */ + if (cfg->pad_config[1] & PAD_CFG1_GPIO_DRIVER) + hostsw_own |= gpio_bitmask_within_group(comm, pin); + else + hostsw_own &= ~gpio_bitmask_within_group(comm, pin); + + pcr_write32(dev, hostsw_own_offset, hostsw_own); + + return 0; +} + +static int gpi_enable_smi(struct udevice *dev, const struct pad_config *cfg, + const struct pad_community *comm) +{ + u32 value; + u16 sts_reg; + u16 en_reg; + int group; + int pin; + int ret; + + if ((cfg->pad_config[0] & PAD_CFG0_ROUTE_SMI) != PAD_CFG0_ROUTE_SMI) + return 0; + + pin = relative_pad_in_comm(comm, cfg->pad); + ret = gpio_group_index(comm, pin); + if (ret < 0) + return ret; + group = ret; + + sts_reg = GPI_SMI_STS_OFFSET(comm, group); + value = pcr_read32(dev, sts_reg); + /* Write back 1 to reset the sts bits */ + pcr_write32(dev, sts_reg, value); + + /* Set enable bits */ + en_reg = GPI_SMI_EN_OFFSET(comm, group); + pcr_setbits32(dev, en_reg, gpio_bitmask_within_group(comm, pin)); + + return 0; +} + +static int gpio_configure_itss(struct udevice *dev, + const struct pad_config *cfg, + uint pad_cfg_offset) +{ + struct apl_gpio_priv *priv = dev_get_priv(dev); + + if (!priv->itss_pol_cfg) + return -ENOSYS; + + int irq; + + /* Set up ITSS polarity if pad is routed to APIC. + * + * The ITSS takes only active high interrupt signals. Therefore, + * if the pad configuration indicates an inversion assume the + * intent is for the ITSS polarity. Before forwarding on the + * request to the APIC there's an inversion setting for how the + * signal is forwarded to the APIC. Honor the inversion setting + * in the GPIO pad configuration so that a hardware active low + * signal looks that way to the APIC (double inversion). + */ + if (!(cfg->pad_config[0] & PAD_CFG0_ROUTE_IOAPIC)) + return 0; + + irq = pcr_read32(dev, PAD_CFG1_OFFSET(pad_cfg_offset)); + irq &= PAD_CFG1_IRQ_MASK; + if (!irq) { + log_err("GPIO %u doesn't support APIC routing\n", cfg->pad); + + return -EPROTONOSUPPORT; + } + itss_set_irq_polarity(priv->itss, irq, + cfg->pad_config[0] & PAD_CFG0_RX_POL_INVERT); + + return 0; +} + +/* Number of DWx config registers can be different for different SOCs */ +static uint pad_config_offset(const struct pad_community *comm, uint pad) +{ + size_t offset; + + offset = relative_pad_in_comm(comm, pad); + offset *= GPIO_DWx_SIZE(GPIO_NUM_PAD_CFG_REGS); + + return offset + comm->pad_cfg_base; +} + +static int gpio_pad_reset_config_override(const struct pad_community *comm, + u32 config_value) +{ + const struct reset_mapping *rst_map = comm->reset_map; + int i; + + /* Logical reset values equal chipset values */ + if (!rst_map || !comm->num_reset_vals) + return config_value; + + for (i = 0; i < comm->num_reset_vals; i++, rst_map++) { + if ((config_value & PAD_CFG0_RESET_MASK) == rst_map->logical) { + config_value &= ~PAD_CFG0_RESET_MASK; + config_value |= rst_map->chipset; + + return config_value; + } + } + log_err("Logical-to-Chipset mapping not found\n"); + + return -ENOENT; +} + +static const int mask[4] = { + PAD_CFG0_TX_STATE | \ + PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE | PAD_CFG0_MODE_MASK | + PAD_CFG0_ROUTE_MASK | PAD_CFG0_RXTENCFG_MASK | + PAD_CFG0_RXINV_MASK | PAD_CFG0_PREGFRXSEL | + PAD_CFG0_TRIG_MASK | PAD_CFG0_RXRAW1_MASK | + PAD_CFG0_RXPADSTSEL_MASK | PAD_CFG0_RESET_MASK, + +#ifdef CONFIG_INTEL_GPIO_IOSTANDBY + PAD_CFG1_IOSTERM_MASK | PAD_CFG1_PULL_MASK | PAD_CFG1_IOSSTATE_MASK, +#else + PAD_CFG1_IOSTERM_MASK | PAD_CFG1_PULL_MASK, +#endif + + PAD_CFG2_DEBOUNCE_MASK, + + 0, +}; + +/** + * gpio_configure_pad() - Configure a pad + * + * @dev: GPIO device containing the pad (see gpio_get_device()) + * @cfg: Configuration to apply + * @return 0 if OK, -ve on error + */ +static int gpio_configure_pad(struct udevice *dev, const struct pad_config *cfg) +{ + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + const struct pad_community *comm = plat->comm; + uint config_offset; + u32 pad_conf, soc_pad_conf; + int ret; + int i; + + if (IS_ERR(comm)) + return PTR_ERR(comm); + config_offset = pad_config_offset(comm, cfg->pad); + for (i = 0; i < GPIO_NUM_PAD_CFG_REGS; i++) { + pad_conf = pcr_read32(dev, PAD_CFG_OFFSET(config_offset, i)); + + soc_pad_conf = cfg->pad_config[i]; + if (i == 0) { + ret = gpio_pad_reset_config_override(comm, + soc_pad_conf); + if (ret < 0) + return ret; + soc_pad_conf = ret; + } + soc_pad_conf &= mask[i]; + soc_pad_conf |= pad_conf & ~mask[i]; + + log_debug("gpio_padcfg [0x%02x, %02zd] DW%d [0x%08x : 0x%08x : 0x%08x]\n", + comm->port, relative_pad_in_comm(comm, cfg->pad), i, + pad_conf,/* old value */ + cfg->pad_config[i], /* value passed from gpio table */ + soc_pad_conf); /*new value*/ + pcr_write32(dev, PAD_CFG_OFFSET(config_offset, i), + soc_pad_conf); + } + ret = gpio_configure_itss(dev, cfg, config_offset); + if (ret && ret != -ENOSYS) + return log_msg_ret("itss config failed", ret); + ret = gpio_configure_owner(dev, cfg, comm); + if (ret) + return ret; + ret = gpi_enable_smi(dev, cfg, comm); + if (ret) + return ret; + + return 0; +} + +static u32 get_config_reg_addr(struct udevice *dev, uint offset) +{ + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + const struct pad_community *comm = plat->comm; + uint config_offset; + + config_offset = comm->pad_cfg_base + offset * + GPIO_DWx_SIZE(GPIO_NUM_PAD_CFG_REGS); + + return config_offset; +} + +static u32 get_config_reg(struct udevice *dev, uint offset) +{ + uint config_offset = get_config_reg_addr(dev, offset); + + return pcr_read32(dev, config_offset); +} + +static int apl_gpio_direction_input(struct udevice *dev, uint offset) +{ + uint config_offset = get_config_reg_addr(dev, offset); + + pcr_clrsetbits32(dev, config_offset, + PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE | + PAD_CFG0_RX_DISABLE, + PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE); + + return 0; +} + +static int apl_gpio_direction_output(struct udevice *dev, uint offset, + int value) +{ + uint config_offset = get_config_reg_addr(dev, offset); + + pcr_clrsetbits32(dev, config_offset, + PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | + PAD_CFG0_TX_DISABLE, + PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE | + (value ? PAD_CFG0_TX_STATE : 0)); + + return 0; +} + +static int apl_gpio_get_function(struct udevice *dev, uint offset) +{ + uint mode, rx_tx; + u32 reg; + + reg = get_config_reg(dev, offset); + mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT; + if (!mode) { + rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE); + if (rx_tx == PAD_CFG0_TX_DISABLE) + return GPIOF_INPUT; + else if (rx_tx == PAD_CFG0_RX_DISABLE) + return GPIOF_OUTPUT; + } + + return GPIOF_FUNC; +} + +static int apl_gpio_get_value(struct udevice *dev, uint offset) +{ + uint mode, rx_tx; + u32 reg; + + reg = get_config_reg(dev, offset); + mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT; + if (!mode) { + rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE); + if (rx_tx == PAD_CFG0_TX_DISABLE) + return mode & PAD_CFG0_RX_STATE_BIT ? 1 : 0; + else if (rx_tx == PAD_CFG0_RX_DISABLE) + return mode & PAD_CFG0_TX_STATE_BIT ? 1 : 0; + } + + return 0; +} + +int gpio_route_gpe(struct udevice *itss, uint gpe0b, uint gpe0c, uint gpe0d) +{ + struct udevice *gpio_dev; + u32 misccfg_value; + u32 misccfg_clr; + int ret; + + /* Get the group here for community specific MISCCFG register. + * If any of these returns -1 then there is some error in devicetree + * where the group is probably hardcoded and does not comply with the + * PMC group defines. So we return from here and MISCFG is set to + * default. + */ + ret = itss_route_pmc_gpio_gpe(itss, gpe0b); + if (ret) + return ret; + gpe0b = ret; + + ret = itss_route_pmc_gpio_gpe(itss, gpe0c); + if (ret) + return ret; + gpe0c = ret; + + ret = itss_route_pmc_gpio_gpe(itss, gpe0d); + if (ret) + return ret; + gpe0d = ret; + + misccfg_value = gpe0b << MISCCFG_GPE0_DW0_SHIFT; + misccfg_value |= gpe0c << MISCCFG_GPE0_DW1_SHIFT; + misccfg_value |= gpe0d << MISCCFG_GPE0_DW2_SHIFT; + + /* Program GPIO_MISCCFG */ + misccfg_clr = MISCCFG_GPE0_DW2_MASK | MISCCFG_GPE0_DW1_MASK | + MISCCFG_GPE0_DW0_MASK; + + log_debug("misccfg_clr:%x misccfg_value:%x\n", misccfg_clr, + misccfg_value); + uclass_foreach_dev_probe(UCLASS_GPIO, gpio_dev) { + pcr_clrsetbits32(gpio_dev, GPIO_MISCCFG, misccfg_clr, + misccfg_value); + } + + return 0; +} + +static int apl_gpio_early_init(struct udevice *dev) +{ + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + const u32 *ptr; + int i; + + ptr = plat->early_pads; + for (i = 0; i < plat->early_pads_count; i++) { + struct udevice *pad_dev = NULL; + struct pad_config *cfg; + int ret; + + cfg = (struct pad_config *)ptr; + ret = gpio_get_device(cfg->pad, &pad_dev); + if (ret) + return ret; + ret = gpio_configure_pad(pad_dev, cfg); + if (ret) + return ret; + ptr += 1 + plat->num_cfgs; + } + + return 0; +} + +static int apl_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + struct apl_gpio_priv *priv = dev_get_priv(dev); + struct p2sb_child_platdata *pplat; + int size; + int i; + + plat->num_cfgs = 2; +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + int ret; + + size = dev_read_size(dev, "early-pads"); + if (size > 0) { + plat->early_pads = malloc(size); + if (!plat->early_pads) + return -ENOMEM; + size /= sizeof(fdt32_t); + ret = dev_read_u32_array(dev, "early-pads", plat->early_pads, + size); + if (ret) + return ret; + plat->early_pads_count = size / (1 + plat->num_cfgs); + } +#else + struct dtd_intel_apl_gpio *dtplat = &plat->dtplat; + int ret; + + /* + * 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, plat->dtplat.intel_p2sb_port_id); + if (ret) + return log_msg_ret("Could not set port id", ret); + + /* Assume that if everything is 0, it is empty */ + plat->early_pads = dtplat->early_pads; + size = ARRAY_SIZE(dtplat->early_pads); + for (i = 0; i < size;) { + u32 val; + int j; + + for (val = j = 0; j < plat->num_cfgs + 1; j++) + val |= dtplat->early_pads[i + j]; + if (!val) + break; + plat->early_pads_count++; + i += plat->num_cfgs + 1; + } +#endif + /* Attach this device to its community structure */ + pplat = dev_get_parent_platdata(dev); + for (i = 0; i < ARRAY_SIZE(apl_gpio_communities); i++) { + if (apl_gpio_communities[i].port == pplat->pid) + plat->comm = &apl_gpio_communities[i]; + } + if (!plat->comm) { + log_err("Cannot find community for pid %d\n", pplat->pid); + return -EDOM; + } + ret = uclass_first_device_err(UCLASS_ITSS, &priv->itss); + if (ret) + return log_msg_ret("Cannot find ITSS", ret); + + return 0; +} + +static int apl_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *upriv = dev_get_uclass_priv(dev); + struct apl_gpio_platdata *plat = dev_get_platdata(dev); + struct apl_gpio_priv *priv = dev_get_priv(dev); + const struct pad_community *comm = plat->comm; + + upriv->gpio_count = comm->last_pad - comm->first_pad + 1; + upriv->bank_name = dev->name; + if (spl_phase() == PHASE_TPL) + return apl_gpio_early_init(dev); + priv->itss_pol_cfg = true; + + return 0; +} + +static const struct dm_gpio_ops apl_gpio_ops = { + .get_function = apl_gpio_get_function, + .get_value = apl_gpio_get_value, + .direction_input = apl_gpio_direction_input, + .direction_output = apl_gpio_direction_output, +}; + +static const struct udevice_id apl_gpio_ids[] = { + { .compatible = "intel,apl-gpio"}, + { } +}; + +U_BOOT_DRIVER(apl_gpio_drv) = { + .name = "intel_apl_gpio", + .id = UCLASS_GPIO, + .of_match = apl_gpio_ids, + .probe = apl_gpio_probe, + .ops = &apl_gpio_ops, + .ofdata_to_platdata = apl_gpio_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct apl_gpio_priv), + .platdata_auto_alloc_size = sizeof(struct apl_gpio_platdata), +}; diff --git a/arch/x86/include/asm/arch-apollolake/gpio.h b/arch/x86/include/asm/arch-apollolake/gpio.h new file mode 100644 index 00000000000..08306e93e33 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/gpio.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Copyright 2019 Google LLC + * + * Modified from coreboot gpio.h + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_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_apl.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 - GPIO community + * + * 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; +}; + +/** + * gpio_route_gpe() - set the 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 gpio_route_gpe(struct udevice *dev, uint gpe0b, uint gpe0c, uint gpe0d); + +#endif diff --git a/arch/x86/include/asm/arch-apollolake/gpio_apl.h b/arch/x86/include/asm/arch-apollolake/gpio_apl.h new file mode 100644 index 00000000000..0706a5a34a9 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/gpio_apl.h @@ -0,0 +1,491 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Definitions for the GPIO subsystem on Apollolake + * + * Placed in a separate file since some of these definitions can be used from + * assembly code + * + * This file is part of the coreboot project. + * + * Copyright (C) 2015 - 2017 Intel Corp. + * (Written by Alexandru Gagniuc alexandrux.gagniuc@intel.com for Intel Corp.) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_APOLLOLAKE_GPIO_H_ +#define _SOC_APOLLOLAKE_GPIO_H_ + +/* + * 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 num_reset_vals0x39 +#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 + +/* + * Number of PAD config registers in the Soc that have DW0 and DW1. It should + * be 2. + */ +#define GPIO_NUM_PAD_CFG_REGS 2 /* DW0, DW1 */ + +#endif /* _SOC_APOLLOLAKE_GPIO_H_ */ diff --git a/arch/x86/include/asm/arch-apollolake/gpio_defs.h b/arch/x86/include/asm/arch-apollolake/gpio_defs.h new file mode 100644 index 00000000000..ec14f49849b --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/gpio_defs.h @@ -0,0 +1,398 @@ +/* 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_ARCH_GPIO_DEFS_H_ +#define _ASM_ARCH_GPIO_DEFS_H_ + +/* Port ids */ +#if IS_ENABLED(CONFIG_SOC_INTEL_GLK) +#define PID_GPIO_AUDIO 0xC9 +#define PID_GPIO_SCC 0xC8 +#else +#define PID_GPIO_SW 0xC0 +#define PID_GPIO_S 0xC2 +#define PID_GPIO_W 0xC7 +#endif +#define PID_GPIO_NW 0xC4 +#define PID_GPIO_N 0xC5 +#define PID_ITSS 0xD0 +#define PID_RTC 0xD1 + +#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_TxLASTRxE (0x0 << 14) +/* Tx enabled driving 0, Rx disabled and Rx driving 0 back to its controller + * internally */ +#define PAD_CFG1_IOSSTATE_Tx0RxDCRx0 (0x1 << 14) +/* Tx enabled driving 0, Rx disabled and Rx driving 1 back to its controller + * internally */ +#define PAD_CFG1_IOSSTATE_Tx0RXDCRx1 (0x2 << 14) +/* Tx enabled driving 1, Rx disabled and Rx driving 0 back to its controller + * internally */ +#define PAD_CFG1_IOSSTATE_Tx1RXDCRx0 (0x3 << 14) +/* Tx enabled driving 1, Rx disabled and Rx driving 1 back to its controller + * internally */ +#define PAD_CFG1_IOSSTATE_Tx1RxDCRx1 (0x4 << 14) +/* Tx enabled driving 0, Rx enabled */ +#define PAD_CFG1_IOSSTATE_Tx0RxE (0x5 << 14) +/* Tx enabled driving 1, Rx enabled */ +#define PAD_CFG1_IOSSTATE_Tx1RxE (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_TxDRxE (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_COMMON_GPIO_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 + +#if IS_ENABLED(CONFIG_INTEL_GPIO_IOSTANDBY) +#define PAD_IOSSTATE(value) PAD_CFG1_IOSSTATE_##value +#define PAD_IOSTERM(value) PAD_CFG1_IOSTERM_##value +#else +#define PAD_IOSSTATE(value) 0 +#define PAD_IOSTERM(value) 0 +#endif + +#define PAD_IRQ_CFG(route, trig, inv) \ + (PAD_CFG0_ROUTE_##route | \ + PAD_CFG0_TRIG_##trig | \ + PAD_CFG0_RX_POL_##inv) + +#if IS_ENABLED(INTEL_GPIO_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_GPIO_DUAL_ROUTE_SUPPORT */ + +#define _PAD_CFG_STRUCT(__pad, __config0, __config1) \ + { \ + .pad = __pad, \ + .pad_config[0] = __config0, \ + .pad_config[1] = __config1, \ + } + +#if GPIO_NUM_PAD_CFG_REGS > 2 +#define _PAD_CFG_STRUCT_3(__pad, __config0, __config1, __config2) \ + { \ + .pad = __pad, \ + .pad_config[0] = __config0, \ + .pad_config[1] = __config1, \ + .pad_config[2] = __config2, \ + } +#else +#define _PAD_CFG_STRUCT_3(__pad, __config0, __config1, __config2) \ + _PAD_CFG_STRUCT(__pad, __config0, __config1) +#endif + +/* 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(TxLASTRxE)) + +#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(TxLASTRxE) | 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(TxLASTRxE)) + +/* 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(TxLASTRxE)) + +/* 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(TxLASTRxE) | 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(TxDRxE)) + +/* 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(TxDRxE)) + +#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(TxDRxE)) + +/* + * 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(TxDRxE)) + +/* 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(TxDRxE)) + +/* 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(TxDRxE)) + +/* 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(TxDRxE)) + +/* 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(TxDRxE), 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(TxDRxE)) + +#if IS_ENABLED(INTEL_GPIO_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(TxDRxE)) + +#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(TxDRxE)) + +#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_GPIO_DUAL_ROUTE_SUPPORT */ + +#endif /* _ASM_ARCH_GPIO_DEFS_H_ */

Provide definitions for using this device on apollolake. They should perhaps be moved into a more generic place.
Signed-off-by: Simon Glass sjg@chromium.org ---
.../include/asm/arch-apollolake/fast_spi.h | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 arch/x86/include/asm/arch-apollolake/fast_spi.h
diff --git a/arch/x86/include/asm/arch-apollolake/fast_spi.h b/arch/x86/include/asm/arch-apollolake/fast_spi.h new file mode 100644 index 00000000000..ebae1f87ebf --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fast_spi.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef SOC_INTEL_COMMON_BLOCK_FAST_SPI_DEF_H +#define SOC_INTEL_COMMON_BLOCK_FAST_SPI_DEF_H + +/* PCI configuration registers */ + +#define SPIDVID_OFFSET 0x0 +#define SPIBAR_BIOS_CONTROL 0xdc + +/* Bit definitions for BIOS_CONTROL */ +#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) + +/* 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]; + + u8 spare[0x84 - 0x50]; + u32 fpr[8]; + u16 preop; + u16 optype; + u32 opmenu_lower; + u32 opmenu_upper; + + u32 space2; + u32 fdoc; + u32 fdod; + u32 spare3[4]; + 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) +#define SPIBAR_BFPREG_SBRS BIT(31) + +/* Bit definitions for HSFSTS_CTL (0x04) register */ +#define SPIBAR_HSFSTS_FDBC_MASK (0x3f << 24) +#define SPIBAR_HSFSTS_FDBC(n) (((n) << 24) & SPIBAR_HSFSTS_FDBC_MASK) +#define SPIBAR_HSFSTS_WET BIT(21) +#define SPIBAR_HSFSTS_FCYCLE_MASK (0xf << 17) +#define SPIBAR_HSFSTS_FCYCLE(cyc) (((cyc) << 17) \ + & SPIBAR_HSFSTS_FCYCLE_MASK) +/* Supported flash cycle types */ +#define SPIBAR_HSFSTS_CYCLE_READ SPIBAR_HSFSTS_FCYCLE(0) +#define SPIBAR_HSFSTS_CYCLE_WRITE SPIBAR_HSFSTS_FCYCLE(2) +#define SPIBAR_HSFSTS_CYCLE_4K_ERASE SPIBAR_HSFSTS_FCYCLE(3) +#define SPIBAR_HSFSTS_CYCLE_64K_ERASE SPIBAR_HSFSTS_FCYCLE(4) +#define SPIBAR_HSFSTS_CYCLE_RD_STATUS SPIBAR_HSFSTS_FCYCLE(8) + +#define SPIBAR_HSFSTS_FGO BIT(16) +#define SPIBAR_HSFSTS_FLOCKDN BIT(15) +#define SPIBAR_HSFSTS_FDV BIT(14) +#define SPIBAR_HSFSTS_FDOPSS BIT(13) +#define SPIBAR_HSFSTS_WRSDIS BIT(11) +#define SPIBAR_HSFSTS_SAF_CE BIT(8) +#define SPIBAR_HSFSTS_SAF_ACTIVE BIT(7) +#define SPIBAR_HSFSTS_SAF_LE BIT(6) +#define SPIBAR_HSFSTS_SCIP BIT(5) +#define SPIBAR_HSFSTS_SAF_DLE BIT(4) +#define SPIBAR_HSFSTS_SAF_ERROR BIT(3) +#define SPIBAR_HSFSTS_AEL BIT(2) +#define SPIBAR_HSFSTS_FCERR BIT(1) +#define SPIBAR_HSFSTS_FDONE BIT(0) +#define SPIBAR_HSFSTS_W1C_BITS 0xff + +#define WPSR_MASK_SRP0_BIT 0x80 + +/* Bit definitions for FADDR (0x08) register */ +#define SPIBAR_FADDR_MASK 0x7FFFFFF + +/* Bit definitions for DLOCK (0x0C) register */ +#define SPIBAR_DLOCK_PR0LOCKDN BIT(8) +#define SPIBAR_DLOCK_PR1LOCKDN BIT(9) +#define SPIBAR_DLOCK_PR2LOCKDN BIT(10) +#define SPIBAR_DLOCK_PR3LOCKDN BIT(11) +#define SPIBAR_DLOCK_PR4LOCKDN BIT(12) + +/* Maximum bytes of data that can fit in FDATAn (0x10) registers */ +#define SPIBAR_FDATA_FIFO_SIZE 0x40 + +/* Bit definitions for FDOC (0xB4) register */ +#define SPIBAR_FDOC_COMPONENT BIT(12) +#define SPIBAR_FDOC_FDSI_1 BIT(2) + +/* Flash Descriptor Component Section - Component 0 Density Bit Settings */ +#define FLCOMP_C0DEN_MASK 0xF +#define FLCOMP_C0DEN_8MB 4 +#define FLCOMP_C0DEN_16MB 5 +#define FLCOMP_C0DEN_32MB 6 + +/* Bit definitions for FPRn (0x84 + (4 * n)) registers */ +#define SPIBAR_FPR_WPE BIT(31) /* Flash Write protected */ +#define SPIBAR_FPR_MAX 5 + +/* Programmable values for OPMENU_LOWER(0xA8) & OPMENU_UPPER(0xAC) register */ +#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */ +#define SPI_OPTYPE_0 0x01 /* Write, no address */ +#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */ +#define SPI_OPTYPE_1 0x03 /* Write, address required */ +#define SPI_OPMENU_2 0x03 /* READ: Read Data */ +#define SPI_OPTYPE_2 0x02 /* Read, address required */ +#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */ +#define SPI_OPTYPE_3 0x00 /* Read, no address */ +#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */ +#define SPI_OPTYPE_4 0x03 /* Write, address required */ +#define SPI_OPMENU_5 0x9f /* RDID: Read ID */ +#define SPI_OPTYPE_5 0x00 /* Read, no address */ +#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */ +#define SPI_OPTYPE_6 0x03 /* Write, address required */ +#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */ +#define SPI_OPTYPE_7 0x02 /* Read, address required */ +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | SPI_OPMENU_4) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | SPI_OPMENU_0) +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0)) +#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */ + +/* Bit definitions for PTINX (0xCC) register */ +#define SPIBAR_PTINX_COMP_0 (0 << 14) +#define SPIBAR_PTINX_COMP_1 (1 << 14) +#define SPIBAR_PTINX_HORD_SFDP (0 << 12) +#define SPIBAR_PTINX_HORD_PARAM (1 << 12) +#define SPIBAR_PTINX_HORD_JEDEC (2 << 12) +#define SPIBAR_PTINX_IDX_MASK 0xffc + +/* Register Offsets of BIOS Flash Program Registers */ +#define SPIBAR_RESET_LOCK 0xF0 +#define SPIBAR_RESET_CTRL 0xF4 +#define SPIBAR_RESET_DATA 0xF8 + +/* Programmable values of Bit0 (SSL) of Set STRAP MSG LOCK (0xF0) Register */ +#define SPIBAR_RESET_LOCK_DISABLE 0 /* Set_Strap Lock(SSL) Bit 0 = 0 */ +#define SPIBAR_RESET_LOCK_ENABLE 1 /* Set_Strap Lock(SSL) Bit 0 = 1 */ + +/* Programmable values of Bit0(SSMS) of Set STRAP MSG Control (0xF4) Register*/ +#define SPIBAR_RESET_CTRL_SSMC 1 /* Set_Strap Mux Select(SSMS) Bit=1*/ + +#define SPIBAR_HWSEQ_XFER_TIMEOUT_MS 5000 /* max 5s*/ + +ulong fast_spi_get_bios_region(struct fast_spi_regs *regs, size_t *bios_size); + +int fast_spi_get_bios_mmap(ulong *map_basep, size_t *map_sizep, uint *offsetp); + +#endif /* SOC_INTEL_COMMON_BLOCK_FAST_SPI_DEF_H */

This driver handles communication with the systemagent which needs to be told when U-Boot has completed its init.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 2 ++ arch/x86/cpu/apollolake/systemagent.c | 19 ++++++++++++ .../include/asm/arch-apollolake/systemagent.h | 31 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 arch/x86/cpu/apollolake/systemagent.c create mode 100644 arch/x86/include/asm/arch-apollolake/systemagent.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index f985018228a..5d5fc0b5949 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,6 +2,8 @@ # # Copyright (c) 2016 Google, Inc
+obj-$(CONFIG_SPL_BUILD) += systemagent.o + obj-y += gpio.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/systemagent.c b/arch/x86/cpu/apollolake/systemagent.c new file mode 100644 index 00000000000..3a41b329c3d --- /dev/null +++ b/arch/x86/cpu/apollolake/systemagent.c @@ -0,0 +1,19 @@ +// 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 + */ + setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3); +} diff --git a/arch/x86/include/asm/arch-apollolake/systemagent.h b/arch/x86/include/asm/arch-apollolake/systemagent.h new file mode 100644 index 00000000000..5983e4e6302 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/systemagent.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Take from coreboot project file of the same name + */ + +#ifndef __ARCH_SYSTEMAGENT_H +#define __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 0xfffffff000ull +#define VTBAR_SIZE 0x1000 + +void enable_bios_reset_cpl(void); + +#endif

This driver models the hostbridge as a northbridge. It simply sets up the graphics BAR. It supports of-platdata.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/hostbridge.c | 127 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 arch/x86/cpu/apollolake/hostbridge.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 5d5fc0b5949..13113fadc79 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o
obj-y += gpio.o +obj-y += hostbridge.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/hostbridge.c b/arch/x86/cpu/apollolake/hostbridge.c new file mode 100644 index 00000000000..5b3cd6d292a --- /dev/null +++ b/arch/x86/cpu/apollolake/hostbridge.c @@ -0,0 +1,127 @@ +// 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_regs.h> +#include <asm/pci.h> +#include <asm/arch/systemagent.h> + +/** + * struct apl_hostbridge_platdata - platform data for hostbridge + * + * @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 + 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(struct udevice *dev) +{ + struct apl_hostbridge_platdata *plat = dev_get_platdata(dev); + u32 region_size; + u32 reg; + ulong base; + + /* 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); + + return 0; +} + +static int apl_hostbridge_ofdata_to_platdata(struct udevice *dev) +{ + struct apl_hostbridge_platdata *plat = dev_get_platdata(dev); +#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_x86_get_devfn(dev); + if (root < 0) + return log_msg_ret("Cannot get host-bridge PCI address", root); + plat->bdf = root; +#else + plat->pciex_region_size = plat->dtplat.pciex_region_size; + plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]); +#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), +};

This driver models some sort of interrupt thingy but there are so many abreviations that I cannot find out what it stands for. Possibly something to do with interrupts.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/itss.c | 129 ++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/itss.h | 43 +++++++ 3 files changed, 173 insertions(+) create mode 100644 arch/x86/cpu/apollolake/itss.c create mode 100644 arch/x86/include/asm/arch-apollolake/itss.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 13113fadc79..5b7b6489bb0 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o
obj-y += gpio.o obj-y += hostbridge.o +obj-y += itss.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/itss.c b/arch/x86/cpu/apollolake/itss.c new file mode 100644 index 00000000000..40d2480451d --- /dev/null +++ b/arch/x86/cpu/apollolake/itss.c @@ -0,0 +1,129 @@ +// 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 <itss.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; +}; + +static int apl_set_irq_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(uint32_t) * (irq / IRQS_PER_IPC); + mask = 1 << (irq % IRQS_PER_IPC); + + pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0); + + return 0; +} + +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 itss_ops apl_itss_ops = { + .route_pmc_gpio_gpe = apl_route_pmc_gpio_gpe, + .set_irq_polarity = apl_set_irq_polarity, +}; + +static const struct udevice_id apl_itss_ids[] = { + { .compatible = "intel,apl-itss"}, + { } +}; + +U_BOOT_DRIVER(apl_itss_drv) = { + .name = "intel_apl_itss", + .id = UCLASS_ITSS, + .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), +}; diff --git a/arch/x86/include/asm/arch-apollolake/itss.h b/arch/x86/include/asm/arch-apollolake/itss.h new file mode 100644 index 00000000000..3821fc04538 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/itss.h @@ -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 */

This driver the LPC and provides a few functions to set up LPC features. These should probably use ioctls() or perhaps, better, have specific uclass methods.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/lpc.c | 155 +++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/lpc.h | 61 ++++++++ 3 files changed, 217 insertions(+) create mode 100644 arch/x86/cpu/apollolake/lpc.c create mode 100644 arch/x86/include/asm/arch-apollolake/lpc.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 5b7b6489bb0..2bee6b6eb0d 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o obj-y += gpio.o obj-y += hostbridge.o obj-y += itss.o +obj-y += lpc.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/lpc.c b/arch/x86/cpu/apollolake/lpc.c new file mode 100644 index 00000000000..b528c4dc471 --- /dev/null +++ b/arch/x86/cpu/apollolake/lpc.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + * + * From coreboot apollolake 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> + +/* + * TODO(sjg@chromium.org): Move this to device tree +static const struct pad_config lpc_gpios[] = { + PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1), + PAD_CFG_NF(LPC_CLKOUT0, UP_20K, DEEP, NF1), + PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1) +}; +*/ +void lpc_configure_pads(void) +{ +/* gpio_configure_pads(lpc_gpios, ARRAY_SIZE(lpc_gpios)); */ +} + +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), ®, + 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; + + /* ComB Range 2F8h-2FFh [6:4] */ + if (0) { + com_ranges |= LPC_IOD_COMB_RANGE; + com_enable |= LPC_IOE_COMB_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 int apl_lpc_probe(struct udevice *dev) +{ + if (spl_phase() == PHASE_TPL) + lpc_configure_pads(); + + return 0; +} + +static const struct udevice_id apl_lpc_ids[] = { + { .compatible = "intel,apl-lpc" }, + { } +}; + +U_BOOT_DRIVER(apl_lpc_drv) = { + .name = "intel_apl_lpc", + .id = UCLASS_LPC, + .of_match = apl_lpc_ids, + .probe = apl_lpc_probe, +}; diff --git a/arch/x86/include/asm/arch-apollolake/lpc.h b/arch/x86/include/asm/arch-apollolake/lpc.h new file mode 100644 index 00000000000..c619182fd0f --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/lpc.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Take from coreboot project file of the same name + */ + +#ifndef __ARCH_LPC_H +#define __ARCH_LPC_H + +#define LPC_SERIRQ_CTL 0x64 +#define LPC_SCNT_EN (1 << 7) +#define LPC_SCNT_MODE (1 << 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 (1 << 0) +#define LPC_LGIR_MAX_WINDOW_SIZE 256 +#define LPC_GENERIC_MEM_RANGE 0x98 +#define LPC_LGMR_ADDR_MASK 0xffff0000 +#define LPC_LGMR_EN (1 << 0) +#define LPC_LGMR_WINDOW_SIZE (64 * KiB) +#define LPC_BIOS_CNTL 0xdc +#define LPC_BC_BILD (1 << 7) /* BILD */ +#define LPC_BC_LE (1 << 2) /* LE */ +#define LPC_BC_EISS (1 << 5) /* EISS */ +#define LPC_PCCTL 0xE0 /* PCI Clock Control */ +#define LPC_PCCTL_CLKRUN_EN (1 << 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 + +void lpc_enable_fixed_io_ranges(uint io_enables); +int lpc_open_pmio_window(uint base, uint size); +void lpc_io_setup_comm_a_b(void); + +#endif

Add a driver for the apollolake Platform Controller Hub. It does not have any functionality and is just a placeholder for now.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/pch.c | 29 ++++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/pch.h | 9 +++++++ 3 files changed, 39 insertions(+) create mode 100644 arch/x86/cpu/apollolake/pch.c create mode 100644 arch/x86/include/asm/arch-apollolake/pch.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 2bee6b6eb0d..2760c88c153 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -8,5 +8,6 @@ obj-y += gpio.o obj-y += hostbridge.o obj-y += itss.o obj-y += lpc.o +obj-y += pch.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/pch.c b/arch/x86/cpu/apollolake/pch.c new file mode 100644 index 00000000000..a51198f3d83 --- /dev/null +++ b/arch/x86/cpu/apollolake/pch.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <pch.h> + +static int apl_pch_probe(struct udevice *dev) +{ + return 0; +} + +static const struct pch_ops apl_pch_ops = { +}; + +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, + .probe = apl_pch_probe, + .ops = &apl_pch_ops, +}; diff --git a/arch/x86/include/asm/arch-apollolake/pch.h b/arch/x86/include/asm/arch-apollolake/pch.h new file mode 100644 index 00000000000..7f19903a3fe --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/pch.h @@ -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 */

Add a driver for the apollolake power unit. It is modelled as a syscon driver since it only needs to be probed.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 3 + arch/x86/cpu/apollolake/punit.c | 121 +++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 arch/x86/cpu/apollolake/punit.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 2760c88c153..42ba6ce9957 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -3,6 +3,9 @@ # Copyright (c) 2016 Google, Inc
obj-$(CONFIG_SPL_BUILD) += systemagent.o +ifndef CONFIG_TPL_BUILD +obj-y += punit.o +endif
obj-y += gpio.o obj-y += hostbridge.o diff --git a/arch/x86/cpu/apollolake/punit.c b/arch/x86/cpu/apollolake/punit.c new file mode 100644 index 00000000000..1bdc33aad71 --- /dev/null +++ b/arch/x86/cpu/apollolake/punit.c @@ -0,0 +1,121 @@ +// 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> + +/** + * struct apl_punit_platdata - platform data for punit + * + * @pciex_region_size: BAR length in bytes + */ +struct apl_punit_platdata { + pci_dev_t bdf; +}; + +/* + * Punit Initialization code. This all isn't documented, but + * this is the recipe. + */ +static int punit_init(struct udevice *dev) +{ + struct apl_punit_platdata *plat = dev_get_platdata(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 */ + pci_x86_write_config(plat->bdf, PCI_INTERRUPT_PIN, 0x2, PCI_SIZE_8); + + /* 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)); + + if (!IS_ENABLED(SOC_INTEL_GLK)) + clrsetbits_le32(MCHBAR_REG(0x7818), 0x1fe0, 0x220); + + /* 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 int apl_punit_ofdata_to_platdata(struct udevice *dev) +{ + struct apl_punit_platdata *plat = dev_get_platdata(dev); + int root; + + root = pci_x86_get_devfn(dev); + if (root < 0) + return log_msg_ret("Cannot get host-bridge PCI address", root); + plat->bdf = root; + + 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, + .ofdata_to_platdata = apl_punit_ofdata_to_platdata, + .probe = apl_punit_probe, +};

Add loaders for SPL and TPL so that the next stage can be loaded from memory-mapped SPI or, failing that, the Fast SPI driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 2 + arch/x86/cpu/apollolake/spl.c | 122 +++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 arch/x86/cpu/apollolake/spl.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 42ba6ce9957..ba7e93c2f66 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,7 +2,9 @@ # # Copyright (c) 2016 Google, Inc
+obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o + ifndef CONFIG_TPL_BUILD obj-y += punit.o endif diff --git a/arch/x86/cpu/apollolake/spl.c b/arch/x86/cpu/apollolake/spl.c new file mode 100644 index 00000000000..56fb34559f4 --- /dev/null +++ b/arch/x86/cpu/apollolake/spl.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <binman_sym.h> +#include <spl.h> +#include <asm/spl.h> +#include <asm/arch/cpu.h> +#include <asm/arch/fast_spi.h> + +#include <dm.h> +#include <spi_flash.h> + +/* + * We need to read well past the end of the region in order for execution from + * the loaded data to work. It is not clear why. + */ +#define SAFETY_MARGIN 0x4000 + +binman_sym_declare(ulong, u_boot_spl, image_pos); +binman_sym_declare(ulong, u_boot_spl, size); +/* U-Boot image_pos is declared by common/spl/spl.c */ +binman_sym_declare(ulong, u_boot_any, size); + +static ulong get_image_pos(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, u_boot_spl, image_pos) : + binman_sym(ulong, u_boot_any, image_pos); +} + +static ulong get_image_size(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, u_boot_spl, size) : + binman_sym(ulong, u_boot_any, size); +} + +/* 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 = get_image_pos(); + ulong spl_size = get_image_size(); + ulong map_base; + size_t map_size; + uint map_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); + ret = fast_spi_get_bios_mmap(&map_base, &map_size, &map_offset); + if (ret) + return ret; + spl_pos += map_base & ~0xff000000; + debug(", base %lx, pos %lx\n", map_base, spl_pos); + memcpy((void *)spl_image->load_addr, (void *)spl_pos, + spl_size + SAFETY_MARGIN); + + return 0; +} +SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image); + +#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT) + +/* 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 = get_image_pos(); + ulong spl_size = 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 = CONFIG_SPL_TEXT_BASE; + spl_image->load_addr = CONFIG_SPL_TEXT_BASE; + 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 + SAFETY_MARGIN, + (void *)spl_image->load_addr); + 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 = 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

Add a bare-bones CPU driver so that CPUs can be probed.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/cpu.c | 51 ++++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/cpu.h | 21 +++++++++ 3 files changed, 73 insertions(+) create mode 100644 arch/x86/cpu/apollolake/cpu.c create mode 100644 arch/x86/include/asm/arch-apollolake/cpu.h
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index ba7e93c2f66..c0b79ae2861 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o
ifndef CONFIG_TPL_BUILD +obj-y += cpu.o obj-y += punit.o endif
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c new file mode 100644 index 00000000000..f248623eb49 --- /dev/null +++ b/arch/x86/cpu/apollolake/cpu.c @@ -0,0 +1,51 @@ +// 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> + +struct cpu_apollolake_priv { +}; + +static int apollolake_get_info(struct udevice *dev, struct cpu_info *info) +{ + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); +} + +static int apollolake_get_count(struct udevice *dev) +{ + return 4; +} + +static int cpu_x86_apollolake_probe(struct udevice *dev) +{ + return 0; +} + +static const struct cpu_ops cpu_x86_apollolake_ops = { + .get_desc = cpu_x86_get_desc, + .get_info = apollolake_get_info, + .get_count = apollolake_get_count, + .get_vendor = cpu_x86_get_vendor, +}; + +static const struct udevice_id cpu_x86_apollolake_ids[] = { + { .compatible = "intel,apl-cpu" }, + { } +}; + +U_BOOT_DRIVER(cpu_x86_apollolake_drv) = { + .name = "cpu_x86_apollolake", + .id = UCLASS_CPU, + .of_match = cpu_x86_apollolake_ids, + .bind = cpu_x86_bind, + .probe = cpu_x86_apollolake_probe, + .ops = &cpu_x86_apollolake_ops, + .priv_auto_alloc_size = sizeof(struct cpu_apollolake_priv), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/arch/x86/include/asm/arch-apollolake/cpu.h b/arch/x86/include/asm/arch-apollolake/cpu.h new file mode 100644 index 00000000000..2c5f9138ead --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/cpu.h @@ -0,0 +1,21 @@ +/* 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 + +/* Set to true to use the fast SPI driver to boot, instead of mapped SPI */ +#define BOOT_FROM_FAST_SPI_FLASH false + +/* + * We need to read well past the end of the region in order for execution from + * the loaded data to work. It is not clear why. + */ +#define SAFETY_MARGIN 0x4000 + +#endif /* __ASM_ARCH_CPU_H */

Add code to init the system both in TPL and SPL. Each phase has its own procedure.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/cpu_spl.c | 272 ++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 arch/x86/cpu/apollolake/cpu_spl.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index c0b79ae2861..f6b8caafd33 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,6 +2,7 @@ # # Copyright (c) 2016 Google, Inc
+obj-$(CONFIG_SPL_BUILD) += cpu_spl.o obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o
diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c new file mode 100644 index 00000000000..70724ba2dd2 --- /dev/null +++ b/arch/x86/cpu/apollolake/cpu_spl.c @@ -0,0 +1,272 @@ +// 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/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/fast_spi.h> +#include <asm/arch/gpio.h> +#include <asm/arch/gpio_apl.h> +#include <asm/arch/gpio_defs.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 <power/power_mgr.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_gpio_early_init() 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); + } + + apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); +} + +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); +} + +/* + * init_for_uart() - 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. + */ +static void init_for_uart(void) +{ + p2sb_enable_bar(IOMAP_P2SB_BAR); + pch_uart_init(); +} + +static int fast_spi_cache_bios_region(struct udevice *sf) +{ + ulong map_base; + size_t map_size; + u32 offset; + uintptr_t base; + int ret; + + ret = spi_flash_get_mmap(sf, &map_base, &map_size, &offset); + if (ret) + return ret; + + base = (4ULL << 30) - 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 power_mgr_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, *gpio, *serial, *sf, *lpc; + int ret; + + ret = uclass_first_device_err(UCLASS_POWER_MGR, &pmc); + if (ret) + return log_msg_ret("Could not probe PMC", ret); + + /* Clear global reset promotion bit */ + ret = pmc_global_reset_set_enable(pmc, false); + if (ret) + return log_msg_ret("Could not disable global reset", ret); + + enable_pm_timer_emulation(pmc); + + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa); + if (ret) + return log_msg_ret("Cannot set up northbridge", ret); + ret = uclass_first_device_err(UCLASS_P2SB, &p2sb); + if (ret) + return log_msg_ret("Cannot set up p2sb", ret); + ret = uclass_first_device_err(UCLASS_GPIO, &gpio); + if (ret) + return log_msg_ret("Cannot set up gpio", ret); + gd->baudrate = CONFIG_BAUDRATE; + ret = uclass_first_device_err(UCLASS_SERIAL, &serial); + if (ret) + return log_msg_ret("Cannot set up serial", ret); + ret = uclass_first_device_err(UCLASS_SPI_FLASH, &sf); + if (ret) + return log_msg_ret("Cannot set up SPI flash", ret); + ret = fast_spi_cache_bios_region(sf); + if (ret) + return log_msg_ret("Cannot set up BIOS cache", ret); + ret = pmc_disable_tco(pmc); + if (ret) + return log_msg_ret("Could not disable TCO", ret); + ret = pmc_gpe_init(gpio); + if (ret) + return log_msg_ret("Cannot init pmc_gpe", ret); + ret = uclass_first_device_err(UCLASS_LPC, &lpc); + if (ret) + return log_msg_ret("Cannot set up 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_POWER_MGR, &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(); + /* enable_rtc_upper_bank(); */ + + 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 = x86_cpu_init_f(); + if (!ret) + ret = arch_cpu_init_tpl(); + } else if (spl_phase() == PHASE_SPL) { + ret = x86_cpu_reinit_f(); + if (!ret) + ret = arch_cpu_init_spl(); + } + if (ret) + printf("%s: Error %d\n", __func__, ret); + + return ret; +} + +void board_debug_uart_init(void) +{ + init_for_uart(); +}

Adds a driver for the apollolake Primary-to-sideband bus. This supports various child devices. It supposed both device tree and of-platdata.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/p2sb.c | 167 +++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 arch/x86/cpu/apollolake/p2sb.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index f6b8caafd33..973f552cc7f 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -15,6 +15,7 @@ obj-y += gpio.o 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 diff --git a/arch/x86/cpu/apollolake/p2sb.c b/arch/x86/cpu/apollolake/p2sb.c new file mode 100644 index 00000000000..5bb093361f8 --- /dev/null +++ b/arch/x86/cpu/apollolake/p2sb.c @@ -0,0 +1,167 @@ +// 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 (1 << 7) + +/* High Performance Event Timer Configuration */ +#define P2SB_HPTC 0x60 +#define P2SB_HPTC_ADDRESS_ENABLE (1 << 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 for FspMemoryInit to store and retrieve a global data + * pointer + * + * @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_x86_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 == FDT_ADDR_T_NONE) + return -EINVAL; + } +#else + plat->mmio_base = plat->dtplat.early_regs[0]; + plat->bdf = pci_x86_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, +};

Add basic plumbing to allow apollolake support to be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Kconfig | 1 + arch/x86/cpu/Makefile | 1 + arch/x86/cpu/apollolake/Kconfig | 68 +++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 arch/x86/cpu/apollolake/Kconfig
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9d01801ff13..e0e1f617ffd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -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" diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index b6a010ea320..4c151f8c94d 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -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/ diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig new file mode 100644 index 00000000000..dc78577ed03 --- /dev/null +++ b/arch/x86/cpu/apollolake/Kconfig @@ -0,0 +1,68 @@ +# 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 ITSS + imply POWER_MGR + +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 INTEL_GPIO_DUAL_ROUTE_SUPPORT + def_bool y + +config INTEL_GPIO_PADCFG_PADTOL + def_bool n + +config INTEL_GPIO_IOSTANDBY + def_bool y + +config TPL_SIZE_LIMIT + default 0x7800 + +endif

These are mostly specific to a particular SoC. Add the definitions for apollolake.
Signed-off-by: Simon Glass sjg@chromium.org ---
.../asm/arch-apollolake/fsp/fsp_configs.h | 13 ++ .../asm/arch-apollolake/fsp/fsp_m_upd.h | 127 ++++++++++++++++++ .../include/asm/arch-apollolake/fsp/fsp_vpd.h | 11 ++ 3 files changed, 151 insertions(+) create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h
diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h new file mode 100644 index 00000000000..46e54e39994 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h @@ -0,0 +1,13 @@ +/* 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' */ + +#endif diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h new file mode 100644 index 00000000000..a132d7f7b28 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h @@ -0,0 +1,127 @@ +/* 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 + +#define FSP_DRAM_CHANNELS 4 + +struct __packed fsp_upd_header { + u64 signature; + u8 revision; + u8 reserved[23]; +}; + +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 diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h new file mode 100644 index 00000000000..b14f28b2364 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h @@ -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

Add support for coral which is a range of apollolake-based Chromebook released in 2017. This also includes reef released in 2016, since it is based on the same SoC.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/Makefile | 1 + arch/x86/dts/chromebook_coral.dts | 298 ++++++++++++++++++++++ board/google/Kconfig | 15 ++ board/google/chromebook_coral/Kconfig | 43 ++++ board/google/chromebook_coral/MAINTAINERS | 6 + board/google/chromebook_coral/Makefile | 5 + board/google/chromebook_coral/coral.c | 18 ++ configs/chromebook_coral_defconfig | 95 +++++++ doc/board/google/chromebook_coral.rst | 25 ++ include/configs/chromebook_coral.h | 29 +++ 10 files changed, 535 insertions(+) create mode 100644 arch/x86/dts/chromebook_coral.dts create mode 100644 board/google/chromebook_coral/Kconfig create mode 100644 board/google/chromebook_coral/MAINTAINERS create mode 100644 board/google/chromebook_coral/Makefile create mode 100644 board/google/chromebook_coral/coral.c create mode 100644 configs/chromebook_coral_defconfig create mode 100644 doc/board/google/chromebook_coral.rst create mode 100644 include/configs/chromebook_coral.h
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index d4bdf62be6d..be209aaaf8f 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -2,6 +2,7 @@
dtb-y += bayleybay.dtb \ cherryhill.dtb \ + chromebook_coral.dtb \ chromebook_link.dtb \ chromebox_panther.dtb \ chromebook_samus.dtb \ diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts new file mode 100644 index 00000000000..8f50ce2f94d --- /dev/null +++ b/arch/x86/dts/chromebook_coral.dts @@ -0,0 +1,298 @@ +/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/arch-apollolake/gpio_apl.h> +#include <asm/arch-apollolake/gpio_defs.h> +#include <asm/arch-apollolake/iomap.h> +#include <asm/arch-apollolake/pm.h> + +/ { + model = "Google Coral"; + compatible = "google,coral", "intel,apollolake"; + + aliases { + }; + + 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 = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <2>; + intel,apic-id = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <3>; + intel,apic-id = <3>; + }; + + }; + + keyboard { + intel,duplicate-por; + }; + + pci { + compatible = "pci-x86"; + #address-cells = <3>; + #size-cells = <2>; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0xc0000000 0xe0000000 0 0x10000000 + 0x42000000 0x0 0xb0000000 0xd0000000 0 0x10000000 + 0x01000000 0x0 0x1000 0x1000 0 0xefff>; + + 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>; + }; + + 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>; + + gpio_n: n { + compatible = "intel,apl-gpio"; + intel,p2sb-port-id = <PID_GPIO_N>; + }; + + nw { + u-boot,dm-pre-reloc; + compatible = "intel,apl-gpio"; + intel,p2sb-port-id = <PID_GPIO_NW>; + }; + + w { + u-boot,dm-pre-reloc; + compatible = "intel,apl-gpio"; + intel,p2sb-port-id = <PID_GPIO_W>; + }; + + sw { + compatible = "intel,apl-gpio"; + intel,p2sb-port-id = <PID_GPIO_SW>; + }; + + 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 + 0x400 0x100>; + compatible = "intel,apl-pmc"; + gpe0-dwx-mask = <0xf>; + gpe0-dwx-shift-base = <4>; + gpe0-dw = <PMC_GPE_N_31_0 + PMC_GPE_N_63_32 + PMC_GPE_SW_31_0>; + gpe0-sts = <0x20>; + gpe0-en = <0x30>; + }; + + fast-spi@d,2 { + u-boot,dm-pre-reloc; + reg = <0x02006a10 0 0 0 0>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "intel,fast-spi"; + early-regs = <IOMAP_SPI_BASE 0x1000>; + memory-map = <0xff800000 0x00800000>; + + rw-mrc-cache { + label = "rw-mrc-cache"; + reg = <0x003e0000 0x00010000>; + u-boot,dm-pre-reloc; + }; + rw-var-mrc-cache { + label = "rw-mrc-cache"; + reg = <0x003f0000 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; + }; + }; + }; + +}; + +&gpio_n { + u-boot,dm-pre-reloc; + 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_TxLASTRxE) + + GPIO_47 /* UART2 TX */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TxLASTRxE) + + GPIO_75 /* I2S1_BCLK -- PCH_WP */ + (PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_20K | PAD_CFG1_IOSSTATE_TxDRxE) + + /* I2C2 - TPM */ + GPIO_128 /* LPSS_I2C2_SDA */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TxLASTRxE) + GPIO_129 /* LPSS_I2C2_SCL */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TxLASTRxE) + 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_TxDRxE) + + /* + * 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_TxLASTRxE) + >; +}; + +&host_bridge { + 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>; +}; diff --git a/board/google/Kconfig b/board/google/Kconfig index 679a0f10239..1d67fda0676 100644 --- a/board/google/Kconfig +++ b/board/google/Kconfig @@ -60,8 +60,23 @@ config TARGET_CHROMEBOOK_SAMUS_TPL between different A/B versions of SPL/U-Boot, to allow upgrading of almost all U-Boot code in the field.
+config TARGET_CHROMEBOOK_CORAL + bool "Chromebook coral" + help + This is a range of Intel-based laptops released in 2018. They use an + Intel Apollolake CPU. The design supports WiFi, 4GB to 16GB of + LPDDR4 1600MHz SDRAM, PCIe WiFi and Bluetooth, eMMC (typically 32GB), + up two cameras (front-facing 720p and another 5MP option), USB SD + reader, microphone and speakers. It also includes two USB 3 Type A and + two Type C ports. The latter are used as power input and can also + charge external devices as well as a 4K external display. There is a + Chrome OS EC connected on LPC, a Cr50 secure chip from Google and + various display options. OEMs products include Acer Chromebook 11 + (e.g. C732, CB11, CP311) and Lenovo Chromebook (100e, 300e, 500e). + endchoice
+source "board/google/chromebook_coral/Kconfig" source "board/google/chromebook_link/Kconfig" source "board/google/chromebox_panther/Kconfig" source "board/google/chromebook_samus/Kconfig" diff --git a/board/google/chromebook_coral/Kconfig b/board/google/chromebook_coral/Kconfig new file mode 100644 index 00000000000..940bee89b0b --- /dev/null +++ b/board/google/chromebook_coral/Kconfig @@ -0,0 +1,43 @@ +if TARGET_CHROMEBOOK_CORAL + +config SYS_BOARD + default "chromebook_coral" + +config SYS_VENDOR + default "google" + +config SYS_SOC + default "apollolake" + +config SYS_CONFIG_NAME + default "chromebook_coral" + +config SYS_TEXT_BASE + default 0xffe00000 + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select X86_RESET_VECTOR + select INTEL_APOLLOLAKE + select BOARD_ROMSIZE_KB_16384 + +config PCIE_ECAM_BASE + default 0xf0000000 + +config EARLY_POST_CROS_EC + bool "Enable early post to Chrome OS EC" + help + Allow post codes to be sent to the Chroem OS EC early during boot, + to enable monitoring of the boot and debugging when things go wrong. + With this option enabled, the EC console can be used to watch post + codes the first part of boot. + +config SYS_CAR_ADDR + hex + default 0xfef00000 + +config SYS_CAR_SIZE + hex + default 0xc0000 + +endif diff --git a/board/google/chromebook_coral/MAINTAINERS b/board/google/chromebook_coral/MAINTAINERS new file mode 100644 index 00000000000..904227e2e21 --- /dev/null +++ b/board/google/chromebook_coral/MAINTAINERS @@ -0,0 +1,6 @@ +CHROMEBOOK_CORAL_BOARD +M: Simon Glass sjg@chromium.org +S: Maintained +F: board/google/chromebook_coral/ +F: include/configs/chromebook_coral.h +F: configs/chromebook_coral_defconfig diff --git a/board/google/chromebook_coral/Makefile b/board/google/chromebook_coral/Makefile new file mode 100644 index 00000000000..6a27ce3da1b --- /dev/null +++ b/board/google/chromebook_coral/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2019 Google LLC + +obj-y += coral.o diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c new file mode 100644 index 00000000000..dfe0fa484a1 --- /dev/null +++ b/board/google/chromebook_coral/coral.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> + +int arch_misc_init(void) +{ + return 0; +} + +int board_run_command(const char *cmdline) +{ + printf("No command line\n"); + + return 0; +} diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig new file mode 100644 index 00000000000..6636f7c44ea --- /dev/null +++ b/configs/chromebook_coral_defconfig @@ -0,0 +1,95 @@ +CONFIG_X86=y +CONFIG_SYS_TEXT_BASE=0x1110000 +CONFIG_SYS_MALLOC_F_LEN=0x1d00 +CONFIG_SPL_SYS_MALLOC_F_LEN=0xd000 +CONFIG_NR_DRAM_BANKS=8 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_DEBUG_UART_BASE=0xde000000 +CONFIG_DEBUG_UART_CLOCK=1843200 +CONFIG_VENDOR_GOOGLE=y +CONFIG_TARGET_CHROMEBOOK_CORAL=y +CONFIG_DEBUG_UART=y +CONFIG_FSP_VERSION2=y +CONFIG_HAVE_ACPI_RESUME=y +CONFIG_INTEL_CAR_CQOS=y +CONFIG_X86_OFFSET_U_BOOT=0xffe00000 +CONFIG_X86_OFFSET_SPL=0xffe80000 +CONFIG_SPL_TEXT_BASE=0xfef10000 +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_SPL_LOG=y +CONFIG_LOG_DEFAULT_LEVEL=7 +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_LAST_STAGE_INIT=y +CONFIG_BLOBLIST=y +# CONFIG_TPL_BLOBLIST is not set +CONFIG_BLOBLIST_ADDR=0x100000 +CONFIG_HANDOFF=y +CONFIG_TPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_CPU_SUPPORT=y +CONFIG_SPL_NET_SUPPORT=y +CONFIG_SPL_PCI=y +# CONFIG_TPL_SPI_SUPPORT is not set +CONFIG_HUSH_PARSER=y +CONFIG_CMD_CPU=y +CONFIG_CMD_PMC=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_PART=y +CONFIG_CMD_SATA=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +CONFIG_CMD_SOUND=y +CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_MAC_PARTITION=y +# CONFIG_SPL_MAC_PARTITION is not set +# CONFIG_SPL_DOS_PARTITION is not set +CONFIG_ISO_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="chromebook_coral" +# CONFIG_NET is not set +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_CPU=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_DW=y +CONFIG_TPL_MISC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y +# CONFIG_SPI_FLASH is not set +CONFIG_SPI_FLASH_INTEL_FAST=y +# CONFIG_X86_PCH7 is not set +# CONFIG_X86_PCH9 is not set +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_SOUND=y +CONFIG_SOUND_I8254=y +CONFIG_SOUND_RT5677=y +CONFIG_SPI=y +CONFIG_TPL_SYSRESET=y +CONFIG_TPM_TIS_LPC=y +CONFIG_USB_STORAGE=y +CONFIG_USB_KEYBOARD=y +# CONFIG_DM_VIDEO is not set +CONFIG_SPL_FS_CBFS=y +# CONFIG_SPL_USE_TINY_PRINTF is not set +CONFIG_TPL_USE_TINY_PRINTF=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_TPM=y +# CONFIG_EFI_LOADER is not set diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst new file mode 100644 index 00000000000..bf384b5e942 --- /dev/null +++ b/doc/board/google/chromebook_coral.rst @@ -0,0 +1,25 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Simon Glass sjg@chromium.org + +Chromebook Coral +================ + +Here are some random notes, to be expanded. + +Hob size returned from FSP is about 53KB. + +Partial ROM map + +fef07000 TPL/SPL Stack top +fef10000 +fef16000 2a000 FSP M default stack +fef40000 SPL +fef71000 59000 FSP M +fefca000 + +Partial memory map + +CONFIG_BLOBLIST_ADDR=0x100000 + + +[1] Intel PDF https://www.coreboot.org/images/2/23/Apollolake_SoC.pdf diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h new file mode 100644 index 00000000000..5e447362ada --- /dev/null +++ b/include/configs/chromebook_coral.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 Google LLC + */ + +/* + * board/config.h - configuration options, board-specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <configs/x86-common.h> +#include <configs/x86-chromebook.h> + +#undef CONFIG_STD_DEVICES_SETTINGS +#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,i8042-kbd,serial\0" \ + "stdout=vidconsole,serial\0" \ + "stderr=vidconsole,serial\0" + +#define CONFIG_ENV_SECT_SIZE 0x1000 +#define CONFIG_ENV_OFFSET 0x003f8000 + +#define CONFIG_TPL_TEXT_BASE 0xffff8000 + +#define CONFIG_SYS_NS16550_MEM32 +#undef CONFIG_SYS_NS16550_PORT_MAPPED + +#endif /* __CONFIG_H */

Add some pre-computed binary MRC data so that memory init does not take nearly 30 seconds to run on the first boot.
At present every time U-Boot is flashed, coral takes nearly 30 seconds to boot the first time. Add an initial MRC cache to speed this up. This is somewhat dangerous since the data is taken from just one board, so your mileage may vary.
This patch should not be applied.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 11 +++++++++++ board/google/chromebook_coral/rw-mrc-cache | Bin 0 -> 65536 bytes board/google/chromebook_coral/rw-var-mrc-cache | Bin 0 -> 4096 bytes 3 files changed, 11 insertions(+) create mode 100644 board/google/chromebook_coral/rw-mrc-cache create mode 100644 board/google/chromebook_coral/rw-var-mrc-cache
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index d9a4ca1184e..bf623ba0a57 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -134,6 +134,17 @@ #endif fdtmap { }; + rw-mrc-cache { + type = "blob"; + offset = <0xff3e0000>; + size = <0x10000>; + filename = "board/google/chromebook_coral/rw-mrc-cache"; + }; + rw-var-mrc-cache { + type = "blob"; + size = <0x1000>; + filename = "board/google/chromebook_coral/rw-var-mrc-cache"; + }; #ifdef CONFIG_HAVE_CMC intel-cmc { filename = CONFIG_CMC_FILE; diff --git a/board/google/chromebook_coral/rw-mrc-cache b/board/google/chromebook_coral/rw-mrc-cache new file mode 100644 index 0000000000000000000000000000000000000000..931f7e251c46e03640d46756d5cb2915ec7efef4 GIT binary patch literal 65536 zcmeI5O>7%Q6vt=0w&U-w*pBVkaa9CTFNM-1ZE2B$T2K&eRh9MtROP_AQt7>FfL;m$ z1x}O?VW0=#7*r0xq1RqHbD$Cummc7N)JjP3{_&2owY;0ncu}1A|D@NM-Fffr?9bhu zeY2b0Q)iE#xU;6z=~vadoI88^M6zEkDb;x8u&T+DSNn|?{~l2)FZxtksd-Ubx$G!) zRdiYOq^PY_#L=s^agt9fb!M+p87a%6wo=gIDOwS2qE49z0?UspwNDPPQ&OUCD?i&h z4*1<3ShiifYwI}RH*Wn=F{SRw@tKek_3f9%MWvt%3;oirM~B4isHg;5*I`k@*vz~B z2c$%On1r!GKMsrHl<F5JjLop^+pLq}P#G=z1TgI={cNPE=jy7IP+Q4}BNU_Q2qUWP z<{$NoM>S@xq#g}yxil7srl;>2`K6#E3pjh#GGOD&UTRgnmFcCMH{VTv_myQBrEa;N zrnC%%t4^<4hEb|2o?f*K^g-Oxk!~cgiwVf3Y9#q!RdPWk8golqWY;AJL{50cEp6je z#L=s^ahCUrr(Co=A;D@=+R6iQOv!nEzi0>Nd&*=HaHnBxcY56N!Ov}XWWX<~d@!p1 z{2|BYpEyS4f-^f77oFaG@ZiA#e4!VS3my~2=^1&}FbQKLNvSfre^?MtJM8>ykb4^S zJFS{_lzukS6p7>|O3_v1d&4A*jrjEjbXce`>r6gq$}m3vn@wc-U_?C}i$l}1FXNUE zme=&^oe#@<-nsipD%HC2lc%d&tC~Epw>7sxYi}+%(opEl1yQ#Y=7W~t=(ei~)MW3x zYP+-ZGHMmwT=1oRwozm{O7g&KZZ7zSl(r)2TO|45i;@p&xfpp_%G?MSB@d-PX}QjH zM603{64(lXsPe%twzAOx+o<xdaqG|Ta%}!3`nTvmV{x3C`+~>?QMVK1de4aB6ozt` zgt0+FicTPoUve781~H(pMZPyo!q^P+vss56up)|_&@UehV<YZ8kFHAHR!km<lJ^G( zC^8=$05Y)HOMkpl`u4_(lizb>Z6$60|K}Swu*nMtwi9-d`CwR5v?GD-BT$n~d)2ll zCy)b5KKO!^=TWzm3vMoWQOZkWkPqf@;Ujuf`ht6ewo;R8OWYqkE{c1ElnEm+(xj+T zQRRcTBf|cDL~+KgKXJLxyf4S+lTsGP;-YhYzMlso7d(tdEUg5N$h#!S`g5bhf`qY= z&aB^GL>#|7E{qNCQNkZ3^3Y)t#%7qG%{t_IMyGuOn0AzYHqx{z+H*_PZ3WlxCKp6~ zTZQ)rgYl2s{lTx_fA1qz`BD9lzVTq?)3@&g_dcNYGq=r@0j5Ds%m;($u#E&rfCP3v z0nDf4q9rR@5XCc9SVoC;D2<xuv0!HuZN?An#?ScX+;)^u*m$=kixd(d0TLhq64){U zj3wT&1!ED`nehi>nHh7i&O5f@FCo!}b!KcbW1WeMWwaYV*qiNPTNDx?0TLhq60jkF zu>@lc#ubxCVV%jV%s7S#Wz?Y<w_t0=B8*K~k9F{cElM-CVcD#M4Q$Q!q)H(H5+DH* zAb~9tz&K)ZCe*#lX1yuRm}JH`lty6#U$cxc3hS_J)|+LFcV?YbDI`DwB(S>(EXt!c z3%;)g=<jP78x^~!<z;$-k4Bx*2lRP;Ch##wd4Z;`=-^jpUUsfJ%g!jT4c%S8A@_y^ zCY^v*c+*?|-|c0g<qXz854tD1IC|zvQYGa5c(4dO3mS8lBtQZrKmsH{0wh2JBtQZr zKmsH{0=t#Kl2Y+>A(zi&Q^hGK5t9jnc)QV>?aXzX)%r|nx?HIxrxI~_iC8R`$>s~G zbg@*QsaDF<wYheuDW=_GI+ZQtbD4Z0n=WQ@sicZ0Vve4YAniuC*(%Rerc2dYJuE}~ zq2Fd2HdeHDH`NI51BkXOQAg`fyyM+S{u0K<-+QCwkY3W4^lO3BQV--^1^adId(5vp zmz^u38<ANf0TP&G0-T(m<X@lrP68xA0wh2JBtQZrKmsH{0wh2JJCDGU%!7xWe2+U* ziKI-@H`{aF)@-9wovGJk+Pxgp>k(8kF%@@WO6LpdOe&izmTJ}d^h~+ZmRb5{tI-Wh zXS0d<?R!h#E}opnQ}YMcU!3XxGljA7_ugok*U#za^~u1=`G@jh8Ak_yROXg*O{V5Y z`Jm25pI9RS64?0!I61%be?#s836KB@kN^pg011!)36KB@kN^ox5`iU|oHtLtZ#Ma! z&7{(~V!lwGnJ(4p)k?S1YPM$^b6Uq_PF`Mfm`9{sCZ?yHWFoHSy6sM5w$-f5WAk`= zJ}g&G&W9xxq20Vp%rB_m&tiqK3Dc!>`k20^Uk{v|uj!ONF3-*f#k(L=^B0{_zHS&4 zooysQ0y~WWC+BzCFUJ0o011!)36KB@kN^pg011!)36Q{K6IhbTdGqA^W|Qw`5`M5W z1gEq-JRgranQS_hD-`q7rI|`y=H=&RTb*{Z+c0*Um193Sue0(#;X%=h@}VWUM}Zc6 zrD;Q=dTr3CH%|tCH?zFaQ`GQv4SZ!o>tEKC`YrbCug4zCy{Xi{6cQi-5+DH*AOR8} z0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq z5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5*Skg F{{cmnsVo2h
literal 0 HcmV?d00001
diff --git a/board/google/chromebook_coral/rw-var-mrc-cache b/board/google/chromebook_coral/rw-var-mrc-cache new file mode 100644 index 0000000000000000000000000000000000000000..73183cdd778ba152dfc5f6f516f879454dbf2faf GIT binary patch literal 4096 zcmeYba(0nmU|@K)8%O{_^HQ&!VyE@*KzIxcmOqcVfY|?sDe#5*zxy4;$KL+SUv=~B z>4f>;ZTlxMdzgCvKg|DfryxH5_m`tmanltinE$6a`?i7D!`1(z{u&K|(GVC7fzc2c Y4S~@R7!85Z5Eu=C(GVC7fsqmd0PQ=I{Qv*}
literal 0 HcmV?d00001

Hi Simon,
On Wed, Sep 25, 2019 at 11:02 PM Simon Glass sjg@chromium.org wrote:
The current 'fsp' command only works with FSP1. Update it to avoid trying to build it with FSP2.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 144b1cf5abe..c50ddccef57 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -3,4 +3,4 @@ obj-y += mtrr.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o obj-$(CONFIG_USE_HOB) += hob.o -obj-$(CONFIG_HAVE_FSP) += fsp.o +obj-$(CONFIG_FSP_VERSION1) += fsp.o
Instead of making this command FSP1 only, can we update the codes to support FSP2? It only need output some basic information for the FSP2 file headers.
--
Regards, Bin
participants (2)
-
Bin Meng
-
Simon Glass