[PATCH v7 04/17] x86: apl: Add hostbridge driver

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Fix comments for struct apl_hostbridge_platdata
Changes in v5: None Changes in v4: - Avoid needing to know internals of pinctrl in this driver - Move code to pinctrl driver - Switch over to use pinctrl for pad init/config
Changes in v3: - Move pad programming into the hostbridge to reduce TPL device-tree size - Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/hostbridge.c | 179 +++++++++++++++++++++++++++ 2 files changed, 180 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 3a8c2f66a3..4d3c08f84e 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -4,5 +4,6 @@
obj-$(CONFIG_SPL_BUILD) += systemagent.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 0000000000..793853d5b5 --- /dev/null +++ b/arch/x86/cpu/apollolake/hostbridge.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> +#include <spl.h> +#include <asm/intel_pinctrl.h> +#include <asm/intel_regs.h> +#include <asm/pci.h> +#include <asm/arch/systemagent.h> + +/** + * struct apl_hostbridge_platdata - platform data for hostbridge + * + * @dtplat: Platform data for of-platdata + * @early_pads: Early pad data to set up, each (pad, cfg0, cfg1) + * @early_pads_count: Number of pads to process + * @pciex_region_size: BAR length in bytes + * @bdf: Bus/device/function of hostbridge + */ +struct apl_hostbridge_platdata { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_intel_apl_hostbridge dtplat; +#endif + u32 *early_pads; + int early_pads_count; + uint pciex_region_size; + pci_dev_t bdf; +}; + +enum { + PCIEXBAR = 0x60, + PCIEXBAR_LENGTH_256MB = 0, + PCIEXBAR_LENGTH_128MB, + PCIEXBAR_LENGTH_64MB, + + PCIEXBAR_PCIEXBAREN = 1 << 0, + + TSEG = 0xb8, /* TSEG base */ +}; + +static int apl_hostbridge_early_init_pinctrl(struct udevice *dev) +{ + struct apl_hostbridge_platdata *plat = dev_get_platdata(dev); + struct udevice *pinctrl; + int ret; + + ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl); + if (ret) + return log_msg_ret("no hostbridge pinctrl", ret); + + return pinctrl_config_pads(pinctrl, plat->early_pads, + plat->early_pads_count); +} + +static int apl_hostbridge_early_init(struct udevice *dev) +{ + struct apl_hostbridge_platdata *plat = dev_get_platdata(dev); + u32 region_size; + ulong base; + u32 reg; + int ret; + + /* Set up the MCHBAR */ + pci_x86_read_config(plat->bdf, MCHBAR, &base, PCI_SIZE_32); + base = MCH_BASE_ADDRESS; + pci_x86_write_config(plat->bdf, MCHBAR, base | 1, PCI_SIZE_32); + + /* + * The PCIEXBAR is assumed to live in the memory mapped IO space under + * 4GiB + */ + pci_x86_write_config(plat->bdf, PCIEXBAR + 4, 0, PCI_SIZE_32); + + switch (plat->pciex_region_size >> 20) { + default: + case 256: + region_size = PCIEXBAR_LENGTH_256MB; + break; + case 128: + region_size = PCIEXBAR_LENGTH_128MB; + break; + case 64: + region_size = PCIEXBAR_LENGTH_64MB; + break; + } + + reg = CONFIG_MMCONF_BASE_ADDRESS | (region_size << 1) + | PCIEXBAR_PCIEXBAREN; + pci_x86_write_config(plat->bdf, PCIEXBAR, reg, PCI_SIZE_32); + + /* + * TSEG defines the base of SMM range. BIOS determines the base + * of TSEG memory which must be at or below Graphics base of GTT + * Stolen memory, hence its better to clear TSEG register early + * to avoid power on default non-zero value (if any). + */ + pci_x86_write_config(plat->bdf, TSEG, 0, PCI_SIZE_32); + + ret = apl_hostbridge_early_init_pinctrl(dev); + if (ret) + return log_msg_ret("pinctrl", ret); + + return 0; +} + +static int apl_hostbridge_ofdata_to_platdata(struct udevice *dev) +{ + struct apl_hostbridge_platdata *plat = dev_get_platdata(dev); + struct udevice *pinctrl; + int ret; + + /* + * The host bridge holds the early pad data needed to get through TPL. + * This is a small amount of data, enough to fit in TPL, so we keep it + * separate from the full pad data, stored in the fsp-s subnode. That + * subnode is not present in TPL, to save space. + */ + ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl); + if (ret) + return log_msg_ret("no hostbridge PINCTRL", ret); +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + int root; + + /* Get length of PCI Express Region */ + plat->pciex_region_size = dev_read_u32_default(dev, "pciex-region-size", + 256 << 20); + + root = pci_get_devfn(dev); + if (root < 0) + return log_msg_ret("Cannot get host-bridge PCI address", root); + plat->bdf = root; + + ret = pinctrl_read_pads(pinctrl, dev_ofnode(dev), "early-pads", + &plat->early_pads, &plat->early_pads_count); + if (ret) + return log_msg_ret("early-pads", ret); +#else + struct dtd_intel_apl_hostbridge *dtplat = &plat->dtplat; + int size; + + plat->pciex_region_size = dtplat->pciex_region_size; + plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]); + + /* Assume that if everything is 0, it is empty */ + plat->early_pads = dtplat->early_pads; + size = ARRAY_SIZE(dtplat->early_pads); + plat->early_pads_count = pinctrl_count_pads(pinctrl, plat->early_pads, + size); + +#endif + + return 0; +} + +static int apl_hostbridge_probe(struct udevice *dev) +{ + if (spl_phase() == PHASE_TPL) + return apl_hostbridge_early_init(dev); + + return 0; +} + +static const struct udevice_id apl_hostbridge_ids[] = { + { .compatible = "intel,apl-hostbridge" }, + { } +}; + +U_BOOT_DRIVER(apl_hostbridge_drv) = { + .name = "intel_apl_hostbridge", + .id = UCLASS_NORTHBRIDGE, + .of_match = apl_hostbridge_ids, + .ofdata_to_platdata = apl_hostbridge_ofdata_to_platdata, + .probe = apl_hostbridge_probe, + .platdata_auto_alloc_size = sizeof(struct apl_hostbridge_platdata), +};

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

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4:
- Tidy up header guards
Changes in v3:
- Add snapshot/restore for IRQs
- Use the IRQ uclass instead of ITSS
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/itss.c | 214 ++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/itss.h | 43 ++++ 3 files changed, 258 insertions(+) create mode 100644 arch/x86/cpu/apollolake/itss.c create mode 100644 arch/x86/include/asm/arch-apollolake/itss.h
applied to u-boot-x86/next, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Drop init of ComB since it is not used - Drop lpc_configure_pads() and probe() function, add a comment about pads
Changes in v5: None Changes in v4: - Add comments for exported functions - Tidy up header guards - Use 'Apollo Lake' - Use BIT() macro a bit more - Use tabs instead of spaces
Changes in v3: - Drop unused code in lpc_configure_pads() - Fix value of LPC_BC_LE
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/lpc.c | 122 +++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/lpc.h | 82 ++++++++++++++ 3 files changed, 205 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 2d78368150..31045a03c1 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 += 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 0000000000..45b2144fc6 --- /dev/null +++ b/arch/x86/cpu/apollolake/lpc.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + * + * From coreboot Apollo Lake support lpc.c + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <asm/lpc_common.h> +#include <asm/pci.h> +#include <asm/arch/iomap.h> +#include <asm/arch/lpc.h> +#include <linux/log2.h> + +void lpc_enable_fixed_io_ranges(uint io_enables) +{ + pci_x86_clrset_config(PCH_DEV_LPC, LPC_IO_ENABLES, 0, io_enables, + PCI_SIZE_16); +} + +/* + * Find the first unused IO window. + * Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ... + */ +static int find_unused_pmio_window(void) +{ + int i; + ulong lgir; + + for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) { + pci_x86_read_config(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i), + &lgir, PCI_SIZE_32); + + if (!(lgir & LPC_LGIR_EN)) + return i; + } + + return -1; +} + +int lpc_open_pmio_window(uint base, uint size) +{ + int i, lgir_reg_num; + u32 lgir_reg_offset, lgir, window_size, alignment; + ulong bridged_size, bridge_base; + ulong reg; + + log_debug("LPC: Trying to open IO window from %x size %x\n", base, + size); + + bridged_size = 0; + bridge_base = base; + + while (bridged_size < size) { + /* Each IO range register can only open a 256-byte window */ + window_size = min(size, (uint)LPC_LGIR_MAX_WINDOW_SIZE); + + /* Window size must be a power of two for the AMASK to work */ + alignment = 1UL << (order_base_2(window_size)); + window_size = ALIGN(window_size, alignment); + + /* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18] */ + lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN; + lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK; + + /* Skip programming if same range already programmed */ + for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) { + pci_x86_read_config(PCH_DEV_LPC, + LPC_GENERIC_IO_RANGE(i), ®, + PCI_SIZE_32); + if (lgir == reg) + return -EALREADY; + } + + lgir_reg_num = find_unused_pmio_window(); + if (lgir_reg_num < 0) { + log_err("LPC: Cannot open IO window: %lx size %lx\n", + bridge_base, size - bridged_size); + log_err("No more IO windows\n"); + + return -ENOSPC; + } + lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num); + + pci_x86_write_config(PCH_DEV_LPC, lgir_reg_offset, lgir, + PCI_SIZE_32); + + log_debug("LPC: Opened IO window LGIR%d: base %lx size %x\n", + lgir_reg_num, bridge_base, window_size); + + bridged_size += window_size; + bridge_base += window_size; + } + + return 0; +} + +void lpc_io_setup_comm_a_b(void) +{ + /* ComA Range 3F8h-3FFh [2:0] */ + u16 com_ranges = LPC_IOD_COMA_RANGE; + u16 com_enable = LPC_IOE_COMA_EN; + + /* Setup I/O Decode Range Register for LPC */ + pci_write_config16(PCH_DEV_LPC, LPC_IO_DECODE, com_ranges); + /* Enable ComA and ComB Port */ + lpc_enable_fixed_io_ranges(com_enable); +} + +static const struct udevice_id apl_lpc_ids[] = { + { .compatible = "intel,apl-lpc" }, + { } +}; + +/* All pads are LPC already configured by the hostbridge, so no probing here */ +U_BOOT_DRIVER(apl_lpc_drv) = { + .name = "intel_apl_lpc", + .id = UCLASS_LPC, + .of_match = apl_lpc_ids, +}; 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 0000000000..5d2adad319 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/lpc.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Take from coreboot project file of the same name + */ + +#ifndef _ASM_ARCH_LPC_H +#define _ASM_ARCH_LPC_H + +#define LPC_SERIRQ_CTL 0x64 +#define LPC_SCNT_EN BIT(7) +#define LPC_SCNT_MODE BIT(6) +#define LPC_IO_DECODE 0x80 +#define LPC_IOD_COMA_RANGE (0 << 0) /* 0x3F8 - 0x3FF COMA*/ +#define LPC_IOD_COMB_RANGE (1 << 4) /* 0x2F8 - 0x2FF COMB*/ +/* + * Use IO_<peripheral>_<IO port> style macros defined in lpc_lib.h + * to enable decoding of I/O locations for a peripheral + */ +#define LPC_IO_ENABLES 0x82 +#define LPC_GENERIC_IO_RANGE(n) ((((n) & 0x3) * 4) + 0x84) +#define LPC_LGIR_AMASK_MASK (0xfc << 16) +#define LPC_LGIR_ADDR_MASK 0xfffc +#define LPC_LGIR_EN BIT(0) +#define LPC_LGIR_MAX_WINDOW_SIZE 256 +#define LPC_GENERIC_MEM_RANGE 0x98 +#define LPC_LGMR_ADDR_MASK 0xffff0000 +#define LPC_LGMR_EN BIT(0) +#define LPC_LGMR_WINDOW_SIZE (64 * KiB) +#define LPC_BIOS_CNTL 0xdc +#define LPC_BC_BILD BIT(7) +#define LPC_BC_LE BIT(1) +#define LPC_BC_EISS BIT(5) +#define LPC_PCCTL 0xE0 /* PCI Clock Control */ +#define LPC_PCCTL_CLKRUN_EN BIT(0) + +/* + * IO decode enable macros are in the format IO_<peripheral>_<IO port>. + * For example, to open ports 0x60, 0x64 for the keyboard controller, + * use IOE_KBC_60_64 macro. For IOE_ macros that do not specify a port range, + * the port range is selectable via the IO decodes register. + */ +#define LPC_IOE_EC_4E_4F BIT(13) +#define LPC_IOE_SUPERIO_2E_2F BIT(12) +#define LPC_IOE_EC_62_66 BIT(11) +#define LPC_IOE_KBC_60_64 BIT(10) +#define LPC_IOE_HGE_208 BIT(9) +#define LPC_IOE_LGE_200 BIT(8) +#define LPC_IOE_FDD_EN BIT(3) +#define LPC_IOE_LPT_EN BIT(2) +#define LPC_IOE_COMB_EN BIT(1) +#define LPC_IOE_COMA_EN BIT(0) +#define LPC_NUM_GENERIC_IO_RANGES 4 + +#define LPC_IO_ENABLES 0x82 + +/** + * lpc_enable_fixed_io_ranges() - enable the fixed I/O ranges + * + * @io_enables: Mask of things to enable (LPC_IOE_.) + */ +void lpc_enable_fixed_io_ranges(uint io_enables); + +/** + * lpc_open_pmio_window() - Open an IO port range + * + * @base: Base I/O address (e.g. 0x800) + * @size: Size of window (e.g. 0x100) + * @return 0 if OK, -ENOSPC if there are no more windows available, -EALREADY + * if already set up + */ +int lpc_open_pmio_window(uint base, uint size); + +/** + * lpc_io_setup_comm_a_b() - Set up basic serial UARTs + * + * Set up the LPC to handle I/O to the COMA/COMB serial UART addresses + * 2f8-2ff and 3f8-3ff. + */ +void lpc_io_setup_comm_a_b(void); + +#endif

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Drop init of ComB since it is not used
- Drop lpc_configure_pads() and probe() function, add a comment about pads
Changes in v5: None Changes in v4:
- Add comments for exported functions
- Tidy up header guards
- Use 'Apollo Lake'
- Use BIT() macro a bit more
- Use tabs instead of spaces
Changes in v3:
- Drop unused code in lpc_configure_pads()
- Fix value of LPC_BC_LE
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/lpc.c | 122 +++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/lpc.h | 82 ++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 arch/x86/cpu/apollolake/lpc.c create mode 100644 arch/x86/include/asm/arch-apollolake/lpc.h
applied to u-boot-x86/next, thanks!

Add a driver for the Apollo Lake Platform Controller Hub. It does not have any functionality and is just a placeholder for now.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4: - Tidy up header guards - Update SPI flash protection only in SPL - apollolake -> Apollo Lake
Changes in v3: None Changes in v2: - Drop probe() function - Implement set_spi_protect()
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/pch.c | 36 ++++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/pch.h | 9 ++++++ 3 files changed, 46 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 31045a03c1..36eefcbad7 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 += 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 0000000000..1a5a985221 --- /dev/null +++ b/arch/x86/cpu/apollolake/pch.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <pch.h> +#include <spl.h> +#include <asm/lpc_common.h> + +#define BIOS_CTRL 0xdc + +static int apl_set_spi_protect(struct udevice *dev, bool protect) +{ + if (spl_phase() == PHASE_SPL) + return lpc_set_spi_protect(dev, BIOS_CTRL, protect); + + return 0; +} + +static const struct pch_ops apl_pch_ops = { + .set_spi_protect = apl_set_spi_protect, +}; + +static const struct udevice_id apl_pch_ids[] = { + { .compatible = "intel,apl-pch" }, + { } +}; + +U_BOOT_DRIVER(apl_pch) = { + .name = "apl_pch", + .id = UCLASS_PCH, + .of_match = apl_pch_ids, + .ops = &apl_pch_ops, +}; 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 0000000000..bf3e1670d2 --- /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 */

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Add a driver for the Apollo Lake Platform Controller Hub. It does not have any functionality and is just a placeholder for now.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4:
- Tidy up header guards
- Update SPI flash protection only in SPL
- apollolake -> Apollo Lake
Changes in v3: None Changes in v2:
- Drop probe() function
- Implement set_spi_protect()
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/pch.c | 36 ++++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/pch.h | 9 ++++++ 3 files changed, 46 insertions(+) create mode 100644 arch/x86/cpu/apollolake/pch.c create mode 100644 arch/x86/include/asm/arch-apollolake/pch.h
applied to u-boot-x86/next, thanks!

Add a driver for the Apollo Lake P-unit (power unit). It is modelled as a syscon driver since it only needs to be probed.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Drop Glacier Lake code - Drop platform data and pre-PCI code, since DM PCI is available in SPL
Changes in v5: None Changes in v4: - Name this P-Unit instead of power unit, in the commit message - apollolake -> Apollo Lake
Changes in v3: - Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 3 + arch/x86/cpu/apollolake/punit.c | 94 ++++++++++++++++++++++++++++++++ 2 files changed, 97 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 36eefcbad7..875d454157 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -3,6 +3,9 @@ # Copyright 2019 Google LLC
obj-$(CONFIG_SPL_BUILD) += systemagent.o +ifndef CONFIG_TPL_BUILD +obj-y += punit.o +endif
obj-y += hostbridge.o obj-y += itss.o diff --git a/arch/x86/cpu/apollolake/punit.c b/arch/x86/cpu/apollolake/punit.c new file mode 100644 index 0000000000..1a131fb0b1 --- /dev/null +++ b/arch/x86/cpu/apollolake/punit.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <asm/cpu.h> +#include <asm/cpu_common.h> +#include <asm/intel_regs.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/systemagent.h> + +/* + * Punit Initialisation code. This all isn't documented, but + * this is the recipe. + */ +static int punit_init(struct udevice *dev) +{ + struct udevice *cpu; + u32 reg; + ulong start; + int ret; + + /* Thermal throttle activation offset */ + ret = uclass_first_device_err(UCLASS_CPU, &cpu); + if (ret) + return log_msg_ret("Cannot find CPU", ret); + cpu_configure_thermal_target(cpu); + + /* + * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR). + * Enable all cores here. + */ + writel(0, MCHBAR_REG(CORE_DISABLE_MASK)); + + /* P-Unit bring up */ + reg = readl(MCHBAR_REG(BIOS_RESET_CPL)); + if (reg == 0xffffffff) { + /* P-unit not found */ + debug("Punit MMIO not available\n"); + return -ENOENT; + } + + /* Set Punit interrupt pin IPIN offset 3D */ + dm_pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x2); + + /* Set PUINT IRQ to 24 and INTPIN LOCK */ + writel(PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER | + PUINT_THERMAL_DEVICE_IRQ_LOCK, + MCHBAR_REG(PUNIT_THERMAL_DEVICE_IRQ)); + + /* Stage0 BIOS Reset Complete (RST_CPL) */ + enable_bios_reset_cpl(); + + /* + * Poll for bit 8 to check if PCODE has completed its action in response + * to BIOS Reset complete. We wait here till 1 ms for the bit to get + * set. + */ + start = get_timer(0); + while (!(readl(MCHBAR_REG(BIOS_RESET_CPL)) & PCODE_INIT_DONE)) { + if (get_timer(start) > 1) { + debug("PCODE Init Done timeout\n"); + return -ETIMEDOUT; + } + udelay(100); + } + debug("PUNIT init complete\n"); + + return 0; +} + +static int apl_punit_probe(struct udevice *dev) +{ + if (spl_phase() == PHASE_SPL) + return punit_init(dev); + + return 0; +} + +static const struct udevice_id apl_syscon_ids[] = { + { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT }, + { } +}; + +U_BOOT_DRIVER(syscon_intel_punit) = { + .name = "intel_punit_syscon", + .id = UCLASS_SYSCON, + .of_match = apl_syscon_ids, + .probe = apl_punit_probe, +};

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Add a driver for the Apollo Lake P-unit (power unit). It is modelled as a syscon driver since it only needs to be probed.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Drop Glacier Lake code
- Drop platform data and pre-PCI code, since DM PCI is available in SPL
Changes in v5: None Changes in v4:
- Name this P-Unit instead of power unit, in the commit message
- apollolake -> Apollo Lake
Changes in v3:
- Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 3 + arch/x86/cpu/apollolake/punit.c | 94 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 arch/x86/cpu/apollolake/punit.c
applied to u-boot-x86/next, thanks!

Binman supports writing the position and size of U-Boot proper and SPL into the previous phase of U-Boot. This allows the next phase to be easily located and loaded.
Add functions to return these useful values, along with symbols to allow TPL to load SPL.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Add new patch with methods to find the position/size of next SPL phase
Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None
common/spl/spl.c | 20 ++++++++++++++++++++ include/spl.h | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index d51dbe9942..c1fce62b91 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -42,6 +42,12 @@ u32 *boot_params_ptr = NULL;
/* See spl.h for information about this */ binman_sym_declare(ulong, u_boot_any, image_pos); +binman_sym_declare(ulong, u_boot_any, size); + +#ifdef CONFIG_TPL +binman_sym_declare(ulong, spl, image_pos); +binman_sym_declare(ulong, spl, size); +#endif
/* Define board data structure */ static bd_t bdata __attribute__ ((section(".data"))); @@ -120,6 +126,20 @@ void spl_fixup_fdt(void) #endif }
+ulong spl_get_image_pos(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, spl, image_pos) : + binman_sym(ulong, u_boot_any, image_pos); +} + +ulong spl_get_image_size(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, spl, size) : + binman_sym(ulong, u_boot_any, size); +} + /* * Weak default function for board specific cleanup/preparation before * Linux boot. Some boards/platforms might not need it, so just provide diff --git a/include/spl.h b/include/spl.h index 08ffddac29..02aa1ff85d 100644 --- a/include/spl.h +++ b/include/spl.h @@ -169,10 +169,29 @@ struct spl_load_info { * We need to know the position of U-Boot in memory so we can jump to it. We * allow any U-Boot binary to be used (u-boot.bin, u-boot-nodtb.bin, * u-boot.img), hence the '_any'. These is no checking here that the correct - * image is found. For * example if u-boot.img is used we don't check that + * image is found. For example if u-boot.img is used we don't check that * spl_parse_image_header() can parse a valid header. + * + * Similarly for SPL, so that TPL can jump to SPL. */ binman_sym_extern(ulong, u_boot_any, image_pos); +binman_sym_extern(ulong, u_boot_any, size); +binman_sym_extern(ulong, spl, image_pos); +binman_sym_extern(ulong, spl, size); + +/** + * spl_get_image_pos() - get the image position of the next phase + * + * This returns the image position to use to load the next phase of U-Boot + */ +ulong spl_get_image_pos(void); + +/** + * spl_get_image_size() - get the size of the next phase + * + * This returns the size to use to load the next phase of U-Boot + */ +ulong spl_get_image_size(void);
/** * spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Binman supports writing the position and size of U-Boot proper and SPL into the previous phase of U-Boot. This allows the next phase to be easily located and loaded.
Add functions to return these useful values, along with symbols to allow TPL to load SPL.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Add new patch with methods to find the position/size of next SPL phase
Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None
common/spl/spl.c | 20 ++++++++++++++++++++ include/spl.h | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-)
applied to u-boot-x86/next, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v7: None Changes in v6: - Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option - Move image pos/size access functions and symbols to generic SPL code
Changes in v5: - Add L2 cache flush functoin - Drop SAFETY_MARGIN
Changes in v4: None Changes in v3: - Add a driver for APL SPI for TPL (using of-platdata) - Support TPL without CONFIG_TPL_SPI_SUPPORT - Support bootstage timing
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 2 + arch/x86/cpu/apollolake/spl.c | 178 +++++++++++++++++++++++++++++++ 2 files changed, 180 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 875d454157..1fde400d77 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,7 +2,9 @@ # # Copyright 2019 Google LLC
+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 0000000000..7ab7243311 --- /dev/null +++ b/arch/x86/cpu/apollolake/spl.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <binman_sym.h> +#include <dm.h> +#include <spi.h> +#include <spl.h> +#include <spi_flash.h> +#include <asm/fast_spi.h> +#include <asm/spl.h> +#include <asm/arch/cpu.h> +#include <asm/arch/iomap.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> + +/* This reads the next phase from mapped SPI flash */ +static int rom_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + ulong spl_pos = spl_get_image_pos(); + ulong spl_size = spl_get_image_size(); + struct udevice *dev; + ulong map_base; + size_t map_size; + uint offset; + int ret; + + spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */ + spl_image->entry_point = spl_phase() == PHASE_TPL ? + CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE; + spl_image->load_addr = spl_image->entry_point; + spl_image->os = IH_OS_U_BOOT; + spl_image->name = "U-Boot"; + debug("Reading from mapped SPI %lx, size %lx", spl_pos, spl_size); + + if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) { + ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev); + if (ret) + return log_msg_ret("spi_flash", ret); + if (!dev) + return log_msg_ret("spi_flash dev", -ENODEV); + ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset); + if (ret) + return log_msg_ret("mmap", ret); + } else { + ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size, + &offset); + if (ret) + return ret; + } + spl_pos += map_base & ~0xff000000; + debug(", base %lx, pos %lx\n", map_base, spl_pos); + bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi"); + memcpy((void *)spl_image->load_addr, (void *)spl_pos, spl_size); + cpu_flush_l1d_to_l2(); + bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI); + + return 0; +} +SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image); + +#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT) + +static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len, + void *buf) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; + + return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); +} + +static int apl_flash_probe(struct udevice *dev) +{ + return spi_flash_std_probe(dev); +} + +/* + * Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also + * need to allocate the parent_platdata since by the time this function is + * called device_bind() has already gone past that step. + */ +static int apl_flash_bind(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(OF_PLATDATA)) { + struct dm_spi_slave_platdata *plat; + struct udevice *spi; + int ret; + + ret = uclass_first_device_err(UCLASS_SPI, &spi); + if (ret) + return ret; + dev->parent = spi; + + plat = calloc(sizeof(*plat), 1); + if (!plat) + return -ENOMEM; + dev->parent_platdata = plat; + } + + return 0; +} + +static const struct dm_spi_flash_ops apl_flash_ops = { + .read = apl_flash_std_read, +}; + +static const struct udevice_id apl_flash_ids[] = { + { .compatible = "jedec,spi-nor" }, + { } +}; + +U_BOOT_DRIVER(winbond_w25q128fw) = { + .name = "winbond_w25q128fw", + .id = UCLASS_SPI_FLASH, + .of_match = apl_flash_ids, + .bind = apl_flash_bind, + .probe = apl_flash_probe, + .priv_auto_alloc_size = sizeof(struct spi_flash), + .ops = &apl_flash_ops, +}; + +/* This uses a SPI flash device to read the next phase */ +static int spl_fast_spi_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + ulong spl_pos = spl_get_image_pos(); + ulong spl_size = spl_get_image_size(); + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev); + if (ret) + return ret; + + spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */ + spl_image->entry_point = spl_phase() == PHASE_TPL ? + CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE; + spl_image->load_addr = spl_image->entry_point; + spl_image->os = IH_OS_U_BOOT; + spl_image->name = "U-Boot"; + spl_pos &= ~0xff000000; + debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size); + ret = spi_flash_read_dm(dev, spl_pos, spl_size, + (void *)spl_image->load_addr); + cpu_flush_l1d_to_l2(); + if (ret) + return ret; + + return 0; +} +SPL_LOAD_IMAGE_METHOD("Fast SPI", 1, BOOT_DEVICE_FAST_SPI, + spl_fast_spi_load_image); + +void board_boot_order(u32 *spl_boot_list) +{ + bool use_spi_flash = IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH); + + if (use_spi_flash) { + spl_boot_list[0] = BOOT_DEVICE_FAST_SPI; + spl_boot_list[1] = BOOT_DEVICE_SPI_MMAP; + } else { + spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP; + spl_boot_list[1] = BOOT_DEVICE_FAST_SPI; + } +} + +#else + +void board_boot_order(u32 *spl_boot_list) +{ + spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP; +} +#endif

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
- Move image pos/size access functions and symbols to generic SPL code
Changes in v5:
- Add L2 cache flush functoin
- Drop SAFETY_MARGIN
Changes in v4: None Changes in v3:
- Add a driver for APL SPI for TPL (using of-platdata)
- Support TPL without CONFIG_TPL_SPI_SUPPORT
- Support bootstage timing
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 2 + arch/x86/cpu/apollolake/spl.c | 178 +++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 arch/x86/cpu/apollolake/spl.c
applied to u-boot-x86/next, thanks!

Add a bare-bones CPU driver so that CPUs can be probed.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Drop unnecessary priv struct and probe method - Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
Changes in v5: - Add L2 cache flush function - Drop SAFETY_MARGIN
Changes in v4: - Change apollolake to apl - Tidy up header guards
Changes in v3: - Add two more defines for the CPU driver - Expand comments for BOOT_FROM_FAST_SPI_FLASH
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 2 ++ arch/x86/cpu/apollolake/cpu.c | 41 ++++++++++++++++++++++ arch/x86/cpu/apollolake/cpu_common.c | 17 +++++++++ arch/x86/include/asm/arch-apollolake/cpu.h | 20 +++++++++++ arch/x86/include/asm/msr-index.h | 1 + 5 files changed, 81 insertions(+) create mode 100644 arch/x86/cpu/apollolake/cpu.c create mode 100644 arch/x86/cpu/apollolake/cpu_common.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 1fde400d77..37e42092ec 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -4,8 +4,10 @@
obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o +obj-y += cpu_common.o
ifndef CONFIG_TPL_BUILD +obj-y += cpu.o obj-y += punit.o endif
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c new file mode 100644 index 0000000000..3d05c82a5c --- /dev/null +++ b/arch/x86/cpu/apollolake/cpu.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <cpu.h> +#include <dm.h> +#include <asm/cpu_common.h> +#include <asm/cpu_x86.h> + +static int apl_get_info(struct udevice *dev, struct cpu_info *info) +{ + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); +} + +static int apl_get_count(struct udevice *dev) +{ + return 4; +} + +static const struct cpu_ops cpu_x86_apl_ops = { + .get_desc = cpu_x86_get_desc, + .get_info = apl_get_info, + .get_count = apl_get_count, + .get_vendor = cpu_x86_get_vendor, +}; + +static const struct udevice_id cpu_x86_apl_ids[] = { + { .compatible = "intel,apl-cpu" }, + { } +}; + +U_BOOT_DRIVER(cpu_x86_apl_drv) = { + .name = "cpu_x86_apl", + .id = UCLASS_CPU, + .of_match = cpu_x86_apl_ids, + .bind = cpu_x86_bind, + .ops = &cpu_x86_apl_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c new file mode 100644 index 0000000000..ba6bda37bc --- /dev/null +++ b/arch/x86/cpu/apollolake/cpu_common.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <asm/cpu_common.h> +#include <asm/msr.h> + +void cpu_flush_l1d_to_l2(void) +{ + struct msr_t msr; + + msr = msr_read(MSR_POWER_MISC); + msr.lo |= FLUSH_DL1_L2; + msr_write(MSR_POWER_MISC, msr); +} 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 0000000000..5e906c5e7d --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/cpu.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ + +#ifndef _ASM_ARCH_CPU_H +#define _ASM_ARCH_CPU_H + +/* Common Timer Copy (CTC) frequency - 19.2MHz */ +#define CTC_FREQ 19200000 + +#define MAX_PCIE_PORTS 6 +#define CLKREQ_DISABLED 0xf + +#ifndef __ASSEMBLY__ +/* Flush L1D to L2 */ +void cpu_flush_l1d_to_l2(void); +#endif + +#endif /* _ASM_ARCH_CPU_H */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 79a9369de1..246c14f815 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -70,6 +70,7 @@ #define MSR_IA32_BBL_CR_CTL 0x00000119 #define MSR_IA32_BBL_CR_CTL3 0x0000011e #define MSR_POWER_MISC 0x00000120 +#define FLUSH_DL1_L2 (1 << 8) #define ENABLE_ULFM_AUTOCM_MASK (1 << 2) #define ENABLE_INDP_AUTOCM_MASK (1 << 3)

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Add a bare-bones CPU driver so that CPUs can be probed.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Drop unnecessary priv struct and probe method
- Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
Changes in v5:
- Add L2 cache flush function
- Drop SAFETY_MARGIN
Changes in v4:
- Change apollolake to apl
- Tidy up header guards
Changes in v3:
- Add two more defines for the CPU driver
- Expand comments for BOOT_FROM_FAST_SPI_FLASH
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 2 ++ arch/x86/cpu/apollolake/cpu.c | 41 ++++++++++++++++++++++ arch/x86/cpu/apollolake/cpu_common.c | 17 +++++++++ arch/x86/include/asm/arch-apollolake/cpu.h | 20 +++++++++++ arch/x86/include/asm/msr-index.h | 1 + 5 files changed, 81 insertions(+) create mode 100644 arch/x86/cpu/apollolake/cpu.c create mode 100644 arch/x86/cpu/apollolake/cpu_common.c create mode 100644 arch/x86/include/asm/arch-apollolake/cpu.h
applied to u-boot-x86/next, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Change comment to apl_hostbridge_early_init_pinctrl, not apl_gpio_early_init - Change commented-out enable_rtc_upper_bank() call to a TODO - Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option - Rename init_for_uart() to board_debug_uart_init() - Use SZ_4G instead of open-coded shift
Changes in v5: None Changes in v4: - Switch over to use pinctrl for pad init/config
Changes in v3: - Adjust fast_spi_cache_bios_region() to avoid using SPI driver - Drop calls to x86_cpu_init_f(), x86_cpu_reinit_f() - Fix build error when debug UART is disabled - Init the p2sb before the northbridge since the latter so it can use GPIOs - Move location of fast_spi.h header file - Shorten log_msg_ret() calls since the function name is always printed - Support TPL without CONFIG_TPL_SPI_SUPPORT (reduces code size)
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/cpu_spl.c | 271 ++++++++++++++++++++++++++++++ 2 files changed, 272 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 37e42092ec..edde122f75 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -2,6 +2,7 @@ # # Copyright 2019 Google LLC
+obj-$(CONFIG_SPL_BUILD) += cpu_spl.o obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o obj-y += cpu_common.o diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c new file mode 100644 index 0000000000..8a39c3128e --- /dev/null +++ b/arch/x86/cpu/apollolake/cpu_spl.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + * + * Portions taken from coreboot + */ + +#include <common.h> +#include <acpi_s3.h> +#include <dm.h> +#include <ec_commands.h> +#include <log.h> +#include <spi_flash.h> +#include <spl.h> +#include <syscon.h> +#include <asm/cpu.h> +#include <asm/cpu_common.h> +#include <asm/cpu_x86.h> +#include <asm/fast_spi.h> +#include <asm/intel_pinctrl.h> +#include <asm/intel_regs.h> +#include <asm/io.h> +#include <asm/msr.h> +#include <asm/mtrr.h> +#include <asm/pci.h> +#include <asm/arch/cpu.h> +#include <asm/arch/gpio.h> +#include <asm/arch/iomap.h> +#include <asm/arch/lpc.h> +#include <asm/arch/pch.h> +#include <asm/arch/systemagent.h> +#include <asm/arch/uart.h> +#include <asm/fsp2/fsp_api.h> +#include <linux/sizes.h> +#include <power/acpi_pmc.h> + +/* Define this here to avoid referencing any drivers for the debug UART 1 */ +#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0) + +static void pch_uart_init(void) +{ + /* + * Set up the pinmux so that the UART rx/tx signals are connected + * outside the SoC. + * + * There are about 500 lines of code required to program the GPIO + * configuration for the UARTs. But it boils down to four writes, and + * for the debug UART we want the minimum possible amount of code before + * the UART is running. So just add the magic writes here. See + * apl_hostbridge_early_init_pinctrl() for the full horror. + */ + if (PCI_FUNC(PCH_DEV_UART) == 1) { + writel(0x40000402, 0xd0c50650); + writel(0x3c47, 0xd0c50654); + writel(0x40000400, 0xd0c50658); + writel(0x3c48, 0xd0c5065c); + } else { /* UART2 */ + writel(0x40000402, 0xd0c50670); + writel(0x3c4b, 0xd0c50674); + writel(0x40000400, 0xd0c50678); + writel(0x3c4c, 0xd0c5067c); + } + +#ifdef CONFIG_DEBUG_UART + apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); +#endif +} + +static void p2sb_enable_bar(ulong bar) +{ + /* Enable PCR Base address in PCH */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar, + PCI_SIZE_32); + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); + + /* Enable P2SB MSE */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND, + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, + PCI_SIZE_8); +} + +/* + * board_debug_uart_init() - Init the debug UART ready for use + * + * This is the minimum init needed to get the UART running. It avoids any + * drivers or complex code, so that the UART is running as soon as possible. + */ +void board_debug_uart_init(void) +{ + p2sb_enable_bar(IOMAP_P2SB_BAR); + pch_uart_init(); +} + +static int fast_spi_cache_bios_region(void) +{ + uint map_size, offset; + ulong map_base, base; + int ret; + + ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE); + if (ret) + return log_msg_ret("early_init", ret); + + ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size, + &offset); + if (ret) + return log_msg_ret("get_mmap", ret); + + base = SZ_4G - map_size; + mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size); + log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size); + + return 0; +} + +static void enable_pm_timer_emulation(struct udevice *pmc) +{ + struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc); + msr_t msr; + + /* + * The derived frequency is calculated as follows: + * (CTC_FREQ * msr[63:32]) >> 32 = target frequency. + * + * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is + * used. + */ + msr.hi = (3579545ULL << 32) / CTC_FREQ; + + /* Set PM1 timer IO port and enable */ + msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR); + debug("PM timer %x %x\n", msr.hi, msr.lo); + msr_write(MSR_EMULATE_PM_TIMER, msr); +} + +static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep) +{ + uint base; + uint size; + + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) { + base = MEC_EMI_BASE; + size = MEC_EMI_SIZE; + } else { + base = EC_HOST_CMD_REGION0; + size = 2 * EC_HOST_CMD_REGION_SIZE; + /* Make sure MEMMAP region follows host cmd region */ + assert(base + size == EC_LPC_ADDR_MEMMAP); + size += EC_MEMMAP_SIZE; + } + + *out_basep = base; + *out_sizep = size; +} + +static void early_ec_init(void) +{ + uint base, size; + + /* + * Set up LPC decoding for the Chrome OS EC I/O port ranges: + * - Ports 62/66, 60/64, and 200->208 + * - Chrome OS EC communication I/O ports + */ + lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 | + LPC_IOE_LGE_200); + google_chromeec_ioport_range(&base, &size); + lpc_open_pmio_window(base, size); +} + +static int arch_cpu_init_tpl(void) +{ + struct udevice *pmc, *sa, *p2sb, *serial, *spi, *lpc; + int ret; + + ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc); + if (ret) + return log_msg_ret("PMC", ret); + + /* Clear global reset promotion bit */ + ret = pmc_global_reset_set_enable(pmc, false); + if (ret) + return log_msg_ret("disable global reset", ret); + + enable_pm_timer_emulation(pmc); + + ret = uclass_first_device_err(UCLASS_P2SB, &p2sb); + if (ret) + return log_msg_ret("p2sb", ret); + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa); + if (ret) + return log_msg_ret("northbridge", ret); + gd->baudrate = CONFIG_BAUDRATE; + ret = uclass_first_device_err(UCLASS_SERIAL, &serial); + if (ret) + return log_msg_ret("serial", ret); + if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) { + ret = uclass_first_device_err(UCLASS_SPI, &spi); + if (ret) + return log_msg_ret("SPI", ret); + } else { + /* Alternative code if we don't have SPI in TPL */ + if (IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH)) + printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL"); + ret = fast_spi_cache_bios_region(); + if (ret) + return log_msg_ret("BIOS cache", ret); + } + ret = pmc_disable_tco(pmc); + if (ret) + return log_msg_ret("disable TCO", ret); + ret = pmc_gpe_init(pmc); + if (ret) + return log_msg_ret("pmc_gpe", ret); + ret = uclass_first_device_err(UCLASS_LPC, &lpc); + if (ret) + return log_msg_ret("lpc", ret); + + early_ec_init(); + + return 0; +} + +/* + * Enables several BARs and devices which are needed for memory init + * - MCH_BASE_ADDR is needed in order to talk to the memory controller + * - HPET is enabled because FSP wants to store a pointer to global data in the + * HPET comparator register + */ +static int arch_cpu_init_spl(void) +{ + struct udevice *pmc, *p2sb; + int ret; + + ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc); + if (ret) + return log_msg_ret("Could not probe PMC", ret); + ret = uclass_first_device_err(UCLASS_P2SB, &p2sb); + if (ret) + return log_msg_ret("Cannot set up p2sb", ret); + + lpc_io_setup_comm_a_b(); + + /* TODO(sjg@chromium.org): Enable upper RTC bank here */ + + ret = pmc_init(pmc); + if (ret < 0) + return log_msg_ret("Could not init PMC", ret); +#ifdef CONFIG_HAVE_ACPI_RESUME + ret = pmc_prev_sleep_state(pmc); + if (ret < 0) + return log_msg_ret("Could not get PMC sleep state", ret); + gd->arch.prev_sleep_state = ret; +#endif + + return 0; +} + +int arch_cpu_init(void) +{ + int ret = 0; + + if (spl_phase() == PHASE_TPL) + ret = arch_cpu_init_tpl(); + else if (spl_phase() == PHASE_SPL) + ret = arch_cpu_init_spl(); + if (ret) + printf("%s: Error %d\n", __func__, ret); + + return ret; +}

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Change comment to apl_hostbridge_early_init_pinctrl, not apl_gpio_early_init
- Change commented-out enable_rtc_upper_bank() call to a TODO
- Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
- Rename init_for_uart() to board_debug_uart_init()
- Use SZ_4G instead of open-coded shift
Changes in v5: None Changes in v4:
- Switch over to use pinctrl for pad init/config
Changes in v3:
- Adjust fast_spi_cache_bios_region() to avoid using SPI driver
- Drop calls to x86_cpu_init_f(), x86_cpu_reinit_f()
- Fix build error when debug UART is disabled
- Init the p2sb before the northbridge since the latter so it can use GPIOs
- Move location of fast_spi.h header file
- Shorten log_msg_ret() calls since the function name is always printed
- Support TPL without CONFIG_TPL_SPI_SUPPORT (reduces code size)
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/cpu_spl.c | 271 ++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 arch/x86/cpu/apollolake/cpu_spl.c
applied to u-boot-x86/next, thanks!

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

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Adds a driver for the Apollo Lake 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
Changes in v7:
- Update comment in apl_p2sb_early_init()
Changes in v6: None Changes in v5: None Changes in v4:
- Detect zero mmio address
- Use BIT() macro bit more
- apollolake -> Apollo Lake
Changes in v3:
- Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/p2sb.c | 166 +++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 arch/x86/cpu/apollolake/p2sb.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Tue, Dec 10, 2019 at 10:11 PM Bin Meng bmeng.cn@gmail.com wrote:
On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Adds a driver for the Apollo Lake 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
Changes in v7:
- Update comment in apl_p2sb_early_init()
Changes in v6: None Changes in v5: None Changes in v4:
- Detect zero mmio address
- Use BIT() macro bit more
- apollolake -> Apollo Lake
Changes in v3:
- Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/p2sb.c | 166 +++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 arch/x86/cpu/apollolake/p2sb.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Add basic plumbing to allow Apollo Lake support to be used.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
Changes in v5: - Enable SMP
Changes in v4: - Enable HAVE_X86_FIT - Enable INTEL_GPIO - Switch over to use pinctrl for pad init/config - Use existing VBT Kconfig option - apollolake -> Apollo Lake
Changes in v3: - Add MMC, video, USB configs - Add an APL_SPI_FLASH_BOOT option to enable non-mmap boot - Fix the incorrect value of CPU_ADDR_BITS
Changes in v2: None
arch/x86/Kconfig | 1 + arch/x86/cpu/Makefile | 1 + arch/x86/cpu/apollolake/Kconfig | 96 +++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 arch/x86/cpu/apollolake/Kconfig
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1d08cb24fb..89b93e5de2 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 0e90a38dc5..5b40838e60 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 0000000000..fcff176c27 --- /dev/null +++ b/arch/x86/cpu/apollolake/Kconfig @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2019 Google LLC +# + +config INTEL_APOLLOLAKE + bool + select FSP_VERSION2 + select HAVE_FSP + select ARCH_MISC_INIT + select USE_CAR + select INTEL_PMC + select TPL_X86_TSC_TIMER_NATIVE + select SPL_PCH_SUPPORT + select TPL_PCH_SUPPORT + select PCH_SUPPORT + select P2SB + imply ENABLE_MRC_CACHE + imply AHCI_PCI + imply SCSI + imply SCSI_AHCI + imply SPI_FLASH + imply USB + imply USB_EHCI_HCD + imply TPL + imply SPL + imply TPL_X86_16BIT_INIT + imply TPL_OF_PLATDATA + imply ACPI_PMC + imply MMC + imply DM_MMC + imply MMC_PCI + imply MMC_SDHCI + imply CMD_MMC + imply VIDEO_FSP + imply PINCTRL_INTEL + imply PINCTRL_INTEL_APL + imply HAVE_VBT + imply HAVE_X86_FIT + imply INTEL_GPIO + imply SMP + +if INTEL_APOLLOLAKE + +config DCACHE_RAM_BASE + default 0xfef00000 + +config DCACHE_RAM_SIZE + default 0xc0000 + +config DCACHE_RAM_MRC_VAR_SIZE + default 0xb0000 + +config CPU_SPECIFIC_OPTIONS + def_bool y + select SMM_TSEG + select X86_RAMTEST + +config SMM_TSEG_SIZE + hex + default 0x800000 + +config MMCONF_BASE_ADDRESS + hex + default 0xe0000000 + +config TPL_SIZE_LIMIT + default 0x7800 + +config CPU_ADDR_BITS + default 39 + +config APL_SPI_FLASH_BOOT + bool "Support booting with SPI-flash driver instead memory-mapped SPI" + select TPL_SPI_FLASH_SUPPORT + select TPL_SPI_SUPPORT + help + This enables SPI and SPI flash in TPL. Without the this only + available boot method is to use memory-mapped SPI. Since this is + actually fast and produces a TPL which is 7KB smaller, memory-mapped + SPI is the default. + +config APL_BOOT_FROM_FAST_SPI_FLASH + bool "Boot using SPI flash driver" + select APL_SPI_FLASH_BOOT + help + This option is separate from APL_SPI_FLASH_BOOT since it is useful to + be able to compare booting speed with the same build. Enable this to + use the SPI-flash driver to load SPL, U-Boot and FSP-M. For technical + reasons FSP-S is currently always loaded from memory-mapped SPI. See + Apollo Lake's arch_fsp_init_r() for details about that. + +config VBT_ADDR + default 0xff3f1000 + +endif

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
Add basic plumbing to allow Apollo Lake support to be used.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
Changes in v5:
- Enable SMP
Changes in v4:
- Enable HAVE_X86_FIT
- Enable INTEL_GPIO
- Switch over to use pinctrl for pad init/config
- Use existing VBT Kconfig option
- apollolake -> Apollo Lake
Changes in v3:
- Add MMC, video, USB configs
- Add an APL_SPI_FLASH_BOOT option to enable non-mmap boot
- Fix the incorrect value of CPU_ADDR_BITS
Changes in v2: None
arch/x86/Kconfig | 1 + arch/x86/cpu/Makefile | 1 + arch/x86/cpu/apollolake/Kconfig | 96 +++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 arch/x86/cpu/apollolake/Kconfig
applied to u-boot-x86/next, thanks!

These are mostly specific to a particular SoC. Add the definitions for Apollo Lake.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Fix FSP-M and FSP-S in comments
Changes in v5: None Changes in v4: - apollolake -> Apollo Lake
Changes in v3: - Add VBT signature - Add structures for FSP-S also - Drop struct fsp_usp_header as it is now in the API file
Changes in v2: None
.../asm/arch-apollolake/fsp/fsp_configs.h | 14 + .../asm/arch-apollolake/fsp/fsp_m_upd.h | 123 ++++++++ .../asm/arch-apollolake/fsp/fsp_s_upd.h | 292 ++++++++++++++++++ .../include/asm/arch-apollolake/fsp/fsp_vpd.h | 11 + 4 files changed, 440 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_s_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 0000000000..9185d94b2b --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_configs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright 2019 Google LLC + */ + +#ifndef __FSP_CONFIGS_H__ +#define __FSP_CONFIGS_H__ + +#define FSPT_UPD_SIGNATURE 0x545F4450554C5041 /* 'APLUPD_T' */ +#define FSPM_UPD_SIGNATURE 0x4D5F4450554C5041 /* 'APLUPD_M' */ +#define FSPS_UPD_SIGNATURE 0x535F4450554C5041 /* 'APLUPD_S' */ +#define VBT_SIGNATURE 0x54425624 + +#endif 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 0000000000..93bee5b2d1 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * Copyright 2019 Google LLC + */ + +#ifndef __ASM_ARCH_FSP_M_UDP_H +#define __ASM_ARCH_FSP_M_UDP_H + +#include <asm/fsp2/fsp_api.h> + +#define FSP_DRAM_CHANNELS 4 + +struct __packed fspm_arch_upd { + u8 revision; + u8 reserved[3]; + void *nvs_buffer_ptr; + void *stack_base; + u32 stack_size; + u32 boot_loader_tolum_size; + u32 boot_mode; + u8 reserved1[8]; +}; + +struct __packed fsp_ram_channel { + u8 rank_enable; + u8 device_width; + u8 dram_density; + u8 option; + u8 odt_config; + u8 tristate_clk1; + u8 mode2_n; + u8 odt_levels; +}; + +struct __packed fsp_m_config { + u32 serial_debug_port_address; + u8 serial_debug_port_type; + u8 serial_debug_port_device; + u8 serial_debug_port_stride_size; + u8 mrc_fast_boot; + u8 igd; + u8 igd_dvmt50_pre_alloc; + u8 igd_aperture_size; + u8 gtt_size; + u8 primary_video_adaptor; + u8 package; + u8 profile; + u8 memory_down; + + u8 ddr3_l_page_size; + u8 ddr3_lasr; + u8 scrambler_support; + u8 interleaved_mode; + u16 channel_hash_mask; + u16 slice_hash_mask; + u8 channels_slices_enable; + u8 min_ref_rate2x_enable; + u8 dual_rank_support_enable; + u8 rmt_mode; + u16 memory_size_limit; + u16 low_memory_max_value; + + u16 high_memory_max_value; + u8 disable_fast_boot; + u8 dimm0_spd_address; + u8 dimm1_spd_address; + struct fsp_ram_channel chan[FSP_DRAM_CHANNELS]; + u8 rmt_check_run; + u16 rmt_margin_check_scale_high_threshold; + u8 ch_bit_swizzling[FSP_DRAM_CHANNELS][32]; + u32 msg_level_mask; + u8 unused_upd_space0[4]; + + u8 pre_mem_gpio_table_pin_num[4]; + u32 pre_mem_gpio_table_ptr; + u8 pre_mem_gpio_table_entry_num; + u8 enhance_port8xh_decoding; + u8 spd_write_enable; + u8 mrc_data_saving; + u32 oem_loading_base; + + u8 oem_file_name[16]; + + void *mrc_boot_data_ptr; + u8 e_mmc_trace_len; + u8 skip_cse_rbp; + u8 npk_en; + u8 fw_trace_en; + u8 fw_trace_destination; + u8 recover_dump; + u8 msc0_wrap; + u8 msc1_wrap; + u32 msc0_size; + + u32 msc1_size; + u8 pti_mode; + u8 pti_training; + u8 pti_speed; + u8 punit_mlvl; + + u8 pmc_mlvl; + u8 sw_trace_en; + u8 periodic_retraining_disable; + u8 enable_reset_system; + + u8 enable_s3_heci2; + u8 unused_upd_space1[3]; + + void *variable_nvs_buffer_ptr; + u8 reserved_fspm_upd[12]; +}; + +/** FSP-M UPD Configuration */ +struct __packed fspm_upd { + struct fsp_upd_header header; + struct fspm_arch_upd arch; + struct fsp_m_config config; + u8 unused_upd_space2[158]; + u16 upd_terminator; +}; + +#endif diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h new file mode 100644 index 0000000000..4a868e80ba --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_s_upd.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright (c) 2016, Intel Corporation. All rights reserved. + * Copyright 2019 Google LLC + */ +#ifndef __ASM_ARCH_FSP_S_UDP_H +#define __ASM_ARCH_FSP_S_UDP_H + +#include <asm/fsp2/fsp_api.h> + +struct __packed fsp_s_config { + u8 active_processor_cores; + u8 disable_core1; + u8 disable_core2; + u8 disable_core3; + u8 vmx_enable; + u8 proc_trace_mem_size; + u8 proc_trace_enable; + u8 eist; + u8 boot_p_state; + u8 enable_cx; + u8 c1e; + u8 bi_proc_hot; + u8 pkg_c_state_limit; + u8 c_state_auto_demotion; + u8 c_state_un_demotion; + u8 max_core_c_state; + u8 pkg_c_state_demotion; + u8 pkg_c_state_un_demotion; + u8 turbo_mode; + u8 hda_verb_table_entry_num; + u32 hda_verb_table_ptr; + u8 p2sb_unhide; + u8 ipu_en; + u8 ipu_acpi_mode; + u8 force_wake; + u32 gtt_mm_adr; + u32 gm_adr; + u8 pavp_lock; + u8 graphics_freq_modify; + u8 graphics_freq_req; + u8 graphics_video_freq; + u8 pm_lock; + u8 dop_clock_gating; + u8 unsolicited_attack_override; + u8 wopcm_support; + u8 wopcm_size; + u8 power_gating; + u8 unit_level_clock_gating; + u8 fast_boot; + u8 dyn_sr; + u8 sa_ipu_enable; + u8 pm_support; + u8 enable_render_standby; + u32 logo_size; + u32 logo_ptr; + u32 graphics_config_ptr; + u8 pavp_enable; + u8 pavp_pr3; + u8 cd_clock; + u8 pei_graphics_peim_init; + u8 write_protection_enable[5]; + u8 read_protection_enable[5]; + u16 protected_range_limit[5]; + u16 protected_range_base[5]; + u8 gmm; + u8 clk_gating_pgcb_clk_trunk; + u8 clk_gating_sb; + u8 clk_gating_sb_clk_trunk; + u8 clk_gating_sb_clk_partition; + u8 clk_gating_core; + u8 clk_gating_dma; + u8 clk_gating_reg_access; + u8 clk_gating_host; + u8 clk_gating_partition; + u8 clk_gating_trunk; + u8 hda_enable; + u8 dsp_enable; + u8 pme; + u8 hd_audio_io_buffer_ownership; + u8 hd_audio_io_buffer_voltage; + u8 hd_audio_vc_type; + u8 hd_audio_link_frequency; + u8 hd_audio_i_disp_link_frequency; + u8 hd_audio_i_disp_link_tmode; + u8 dsp_endpoint_dmic; + u8 dsp_endpoint_bluetooth; + u8 dsp_endpoint_i2s_skp; + u8 dsp_endpoint_i2s_hp; + u8 audio_ctl_pwr_gate; + u8 audio_dsp_pwr_gate; + u8 mmt; + u8 hmt; + u8 hd_audio_pwr_gate; + u8 hd_audio_clk_gate; + u32 dsp_feature_mask; + u32 dsp_pp_module_mask; + u8 bios_cfg_lock_down; + u8 hpet; + u8 hpet_bdf_valid; + u8 hpet_bus_number; + u8 hpet_device_number; + u8 hpet_function_number; + u8 io_apic_bdf_valid; + u8 io_apic_bus_number; + u8 io_apic_device_number; + u8 io_apic_function_number; + u8 io_apic_entry24_119; + u8 io_apic_id; + u8 io_apic_range_select; + u8 ish_enable; + u8 bios_interface; + u8 bios_lock; + u8 spi_eiss; + u8 bios_lock_sw_smi_number; + u8 lpss_s0ix_enable; + u8 unused_upd_space0[1]; + u8 i2c_clk_gate_cfg[8]; + u8 hsuart_clk_gate_cfg[4]; + u8 spi_clk_gate_cfg[3]; + u8 i2c0_enable; + u8 i2c1_enable; + u8 i2c2_enable; + u8 i2c3_enable; + u8 i2c4_enable; + u8 i2c5_enable; + u8 i2c6_enable; + u8 i2c7_enable; + u8 hsuart0_enable; + u8 hsuart1_enable; + u8 hsuart2_enable; + u8 hsuart3_enable; + u8 spi0_enable; + u8 spi1_enable; + u8 spi2_enable; + u8 os_dbg_enable; + u8 dci_en; + u32 uart2_kernel_debug_base_address; + u8 pcie_clock_gating_disabled; + u8 pcie_root_port8xh_decode; + u8 pcie8xh_decode_port_index; + u8 pcie_root_port_peer_memory_write_enable; + u8 pcie_aspm_sw_smi_number; + u8 unused_upd_space1[1]; + u8 pcie_root_port_en[6]; + u8 pcie_rp_hide[6]; + u8 pcie_rp_slot_implemented[6]; + u8 pcie_rp_hot_plug[6]; + u8 pcie_rp_pm_sci[6]; + u8 pcie_rp_ext_sync[6]; + u8 pcie_rp_transmitter_half_swing[6]; + u8 pcie_rp_acs_enabled[6]; + u8 pcie_rp_clk_req_supported[6]; + u8 pcie_rp_clk_req_number[6]; + u8 pcie_rp_clk_req_detect[6]; + u8 advanced_error_reporting[6]; + u8 pme_interrupt[6]; + u8 unsupported_request_report[6]; + u8 fatal_error_report[6]; + u8 no_fatal_error_report[6]; + u8 correctable_error_report[6]; + u8 system_error_on_fatal_error[6]; + u8 system_error_on_non_fatal_error[6]; + u8 system_error_on_correctable_error[6]; + u8 pcie_rp_speed[6]; + u8 physical_slot_number[6]; + u8 pcie_rp_completion_timeout[6]; + u8 ptm_enable[6]; + u8 pcie_rp_aspm[6]; + u8 pcie_rp_l1_substates[6]; + u8 pcie_rp_ltr_enable[6]; + u8 pcie_rp_ltr_config_lock[6]; + u8 pme_b0_s5_dis; + u8 pci_clock_run; + u8 timer8254_clk_setting; + u8 enable_sata; + u8 sata_mode; + u8 sata_salp_support; + u8 sata_pwr_opt_enable; + u8 e_sata_speed_limit; + u8 speed_limit; + u8 unused_upd_space2[1]; + u8 sata_ports_enable[2]; + u8 sata_ports_dev_slp[2]; + u8 sata_ports_hot_plug[2]; + u8 sata_ports_interlock_sw[2]; + u8 sata_ports_external[2]; + u8 sata_ports_spin_up[2]; + u8 sata_ports_solid_state_drive[2]; + u8 sata_ports_enable_dito_config[2]; + u8 sata_ports_dm_val[2]; + u8 unused_upd_space3[2]; + u16 sata_ports_dito_val[2]; + u16 sub_system_vendor_id; + u16 sub_system_id; + u8 crid_settings; + u8 reset_select; + u8 sdcard_enabled; + u8 e_mmc_enabled; + u8 e_mmc_host_max_speed; + u8 ufs_enabled; + u8 sdio_enabled; + u8 gpp_lock; + u8 sirq_enable; + u8 sirq_mode; + u8 start_frame_pulse; + u8 smbus_enable; + u8 arp_enable; + u8 unused_upd_space4; + u16 num_rsvd_smbus_addresses; + u8 rsvd_smbus_address_table[128]; + u8 disable_compliance_mode; + u8 usb_per_port_ctl; + u8 usb30_mode; + u8 unused_upd_space5[1]; + u8 port_usb20_enable[8]; + u8 port_us20b_over_current_pin[8]; + u8 usb_otg; + u8 hsic_support_enable; + u8 port_usb30_enable[6]; + u8 port_us30b_over_current_pin[6]; + u8 ssic_port_enable[2]; + u16 dlane_pwr_gating; + u8 vtd_enable; + u8 lock_down_global_smi; + u16 reset_wait_timer; + u8 rtc_lock; + u8 sata_test_mode; + u8 ssic_rate[2]; + u16 dynamic_power_gating; + u16 pcie_rp_ltr_max_snoop_latency[6]; + u8 pcie_rp_snoop_latency_override_mode[6]; + u8 unused_upd_space6[2]; + u16 pcie_rp_snoop_latency_override_value[6]; + u8 pcie_rp_snoop_latency_override_multiplier[6]; + u8 skip_mp_init; + u8 dci_auto_detect; + u16 pcie_rp_ltr_max_non_snoop_latency[6]; + u8 pcie_rp_non_snoop_latency_override_mode[6]; + u8 tco_timer_halt_lock; + u8 pwr_btn_override_period; + u16 pcie_rp_non_snoop_latency_override_value[6]; + u8 pcie_rp_non_snoop_latency_override_multiplier[6]; + u8 pcie_rp_slot_power_limit_scale[6]; + u8 pcie_rp_slot_power_limit_value[6]; + u8 disable_native_power_button; + u8 power_butter_debounce_mode; + u32 sdio_tx_cmd_cntl; + u32 sdio_tx_data_cntl1; + u32 sdio_tx_data_cntl2; + u32 sdio_rx_cmd_data_cntl1; + u32 sdio_rx_cmd_data_cntl2; + u32 sdcard_tx_cmd_cntl; + u32 sdcard_tx_data_cntl1; + u32 sdcard_tx_data_cntl2; + u32 sdcard_rx_cmd_data_cntl1; + u32 sdcard_rx_strobe_cntl; + u32 sdcard_rx_cmd_data_cntl2; + u32 emmc_tx_cmd_cntl; + u32 emmc_tx_data_cntl1; + u32 emmc_tx_data_cntl2; + u32 emmc_rx_cmd_data_cntl1; + u32 emmc_rx_strobe_cntl; + u32 emmc_rx_cmd_data_cntl2; + u32 emmc_master_sw_cntl; + u8 pcie_rp_selectable_deemphasis[6]; + u8 monitor_mwait_enable; + u8 hd_audio_dsp_uaa_compliance; + u32 ipc[4]; + u8 sata_ports_disable_dynamic_pg[2]; + u8 init_s3_cpu; + u8 skip_punit_init; + u8 unused_upd_space7[4]; + u8 port_usb20_per_port_tx_pe_half[8]; + u8 port_usb20_per_port_pe_txi_set[8]; + u8 port_usb20_per_port_txi_set[8]; + u8 port_usb20_hs_skew_sel[8]; + u8 port_usb20_i_usb_tx_emphasis_en[8]; + u8 port_usb20_per_port_rxi_set[8]; + u8 port_usb20_hs_npre_drv_sel[8]; + u8 reserved_fsps_upd[16]; +}; + +/** struct fsps_upd - FSP-S Configuration */ +struct __packed fsps_upd { + struct fsp_upd_header header; + struct fsp_s_config config; + u8 unused_upd_space2[46]; + u16 upd_terminator; +}; + +#endif 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 0000000000..b14f28b236 --- /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

On Mon, Dec 9, 2019 at 8:41 AM Simon Glass sjg@chromium.org wrote:
These are mostly specific to a particular SoC. Add the definitions for Apollo Lake.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Fix FSP-M and FSP-S in comments
Changes in v5: None Changes in v4:
- apollolake -> Apollo Lake
Changes in v3:
- Add VBT signature
- Add structures for FSP-S also
- Drop struct fsp_usp_header as it is now in the API file
Changes in v2: None
.../asm/arch-apollolake/fsp/fsp_configs.h | 14 + .../asm/arch-apollolake/fsp/fsp_m_upd.h | 123 ++++++++ .../asm/arch-apollolake/fsp/fsp_s_upd.h | 292 ++++++++++++++++++ .../include/asm/arch-apollolake/fsp/fsp_vpd.h | 11 + 4 files changed, 440 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_s_upd.h create mode 100644 arch/x86/include/asm/arch-apollolake/fsp/fsp_vpd.h
applied to u-boot-x86/next, thanks!

The memory and silicon init parts of the FSP need support code to work. Add this for Apollo Lake.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: None Changes in v6: - Drop mention of devicetree for VTD feature - Drop mention of ramstage - Fix various coding style problems - Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option - Use 'No SPI' instead of 'SPI2' as a debug message
Changes in v5: - Allocate the FSP-S data instead of using the stack - Rename APOLLOLAKE_USB2_PORT_MAX
Changes in v4: - Adjust the comment for struct dw_i2c_speed_config - Rename arch_fsp_s_preinit() to arch_fsps_preinit() - Switch over to use pinctrl for pad init/config - Tidy up mixed case in FSP code - apollolake -> Apollo Lake
Changes in v3: - Add bootstage timing for reading vbt - Add fspm_done() hook to handle FSP-S wierdness (it breaks SPI flash) - Don't allow BOOT_FROM_FAST_SPI_FLASH with FSP-S - Set boot_loader_tolum_size to 0 - Use the IRQ uclass instead of ITSS
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 6 + arch/x86/cpu/apollolake/fsp_m.c | 210 ++++++++++ arch/x86/cpu/apollolake/fsp_s.c | 661 +++++++++++++++++++++++++++++++ 3 files changed, 877 insertions(+) create mode 100644 arch/x86/cpu/apollolake/fsp_m.c create mode 100644 arch/x86/cpu/apollolake/fsp_s.c
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index dc6df15dab..1760df54d8 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -10,6 +10,12 @@ obj-y += cpu_common.o ifndef CONFIG_TPL_BUILD obj-y += cpu.o obj-y += punit.o +ifdef CONFIG_SPL_BUILD +obj-y += fsp_m.o +endif +endif +ifndef CONFIG_SPL_BUILD +obj-y += fsp_s.o endif
obj-y += hostbridge.o diff --git a/arch/x86/cpu/apollolake/fsp_m.c b/arch/x86/cpu/apollolake/fsp_m.c new file mode 100644 index 0000000000..5308af8ed4 --- /dev/null +++ b/arch/x86/cpu/apollolake/fsp_m.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <dm.h> +#include <asm/arch/iomap.h> +#include <asm/arch/fsp/fsp_configs.h> +#include <asm/arch/fsp/fsp_m_upd.h> +#include <asm/fsp2/fsp_internal.h> +#include <dm/uclass-internal.h> + +/* + * ODT settings: + * If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A and HIGH for ODT_B, + * choose ODT_A_B_HIGH_HIGH. If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A + * and LOW for ODT_B, choose ODT_A_B_HIGH_LOW. + * + * Note that the enum values correspond to the interpreted UPD fields + * within Ch[3:0]_OdtConfig parameters. + */ +enum { + ODT_A_B_HIGH_LOW = 0 << 1, + ODT_A_B_HIGH_HIGH = 1 << 1, + N_WR_24 = 1 << 5, +}; + +/* + * LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation. + * There are four physical LPDDR4 channels, each 32-bits wide. There are two + * logical channels using two physical channels together to form a 64-bit + * interface to memory for each logical channel. + */ + +enum { + LP4_PHYS_CH0A, + LP4_PHYS_CH0B, + LP4_PHYS_CH1A, + LP4_PHYS_CH1B, + + LP4_NUM_PHYS_CHANNELS, +}; + +/* + * The DQs within a physical channel can be bit-swizzled within each byte. + * Within a channel the bytes can be swapped, but the DQs need to be routed + * with the corresponding DQS (strobe). + */ +enum { + LP4_DQS0, + LP4_DQS1, + LP4_DQS2, + LP4_DQS3, + + LP4_NUM_BYTE_LANES, + DQ_BITS_PER_DQS = 8, +}; + +/* Provide bit swizzling per DQS and byte swapping within a channel */ +struct lpddr4_chan_swizzle_cfg { + u8 dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS]; +}; + +struct lpddr4_swizzle_cfg { + struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS]; +}; + +static void setup_sdram(struct fsp_m_config *cfg, + const struct lpddr4_swizzle_cfg *swizzle_cfg) +{ + const struct lpddr4_chan_swizzle_cfg *sch; + /* Number of bytes to copy per DQS */ + const size_t sz = DQ_BITS_PER_DQS; + int chan; + + cfg->memory_down = 1; + cfg->scrambler_support = 1; + cfg->channel_hash_mask = 0x36; + cfg->slice_hash_mask = 9; + cfg->interleaved_mode = 2; + cfg->channels_slices_enable = 0; + cfg->min_ref_rate2x_enable = 0; + cfg->dual_rank_support_enable = 1; + + /* LPDDR4 is memory down so no SPD addresses */ + cfg->dimm0_spd_address = 0; + cfg->dimm1_spd_address = 0; + + for (chan = 0; chan < 4; chan++) { + struct fsp_ram_channel *ch = &cfg->chan[chan]; + + ch->rank_enable = 1; + ch->device_width = 1; + ch->dram_density = 2; + ch->option = 3; + ch->odt_config = ODT_A_B_HIGH_HIGH; + } + + /* + * CH0_DQB byte lanes in the bit swizzle configuration field are + * not 1:1. The mapping within the swizzling field is: + * indices [0:7] - byte lane 1 (DQS1) DQ[8:15] + * indices [8:15] - byte lane 0 (DQS0) DQ[0:7] + * indices [16:23] - byte lane 3 (DQS3) DQ[24:31] + * indices [24:31] - byte lane 2 (DQS2) DQ[16:23] + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH0B]; + memcpy(&cfg->ch_bit_swizzling[0][0], &sch->dqs[LP4_DQS1], sz); + memcpy(&cfg->ch_bit_swizzling[0][8], &sch->dqs[LP4_DQS0], sz); + memcpy(&cfg->ch_bit_swizzling[0][16], &sch->dqs[LP4_DQS3], sz); + memcpy(&cfg->ch_bit_swizzling[0][24], &sch->dqs[LP4_DQS2], sz); + + /* + * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH0A]; + memcpy(&cfg->ch_bit_swizzling[1][0], &sch->dqs[LP4_DQS0], sz); + memcpy(&cfg->ch_bit_swizzling[1][8], &sch->dqs[LP4_DQS1], sz); + memcpy(&cfg->ch_bit_swizzling[1][16], &sch->dqs[LP4_DQS2], sz); + memcpy(&cfg->ch_bit_swizzling[1][24], &sch->dqs[LP4_DQS3], sz); + + sch = &swizzle_cfg->phys[LP4_PHYS_CH1B]; + memcpy(&cfg->ch_bit_swizzling[2][0], &sch->dqs[LP4_DQS1], sz); + memcpy(&cfg->ch_bit_swizzling[2][8], &sch->dqs[LP4_DQS0], sz); + memcpy(&cfg->ch_bit_swizzling[2][16], &sch->dqs[LP4_DQS3], sz); + memcpy(&cfg->ch_bit_swizzling[2][24], &sch->dqs[LP4_DQS2], sz); + + /* + * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH1A]; + memcpy(&cfg->ch_bit_swizzling[3][0], &sch->dqs[LP4_DQS0], sz); + memcpy(&cfg->ch_bit_swizzling[3][8], &sch->dqs[LP4_DQS1], sz); + memcpy(&cfg->ch_bit_swizzling[3][16], &sch->dqs[LP4_DQS2], sz); + memcpy(&cfg->ch_bit_swizzling[3][24], &sch->dqs[LP4_DQS3], sz); +} + +int fspm_update_config(struct udevice *dev, struct fspm_upd *upd) +{ + struct fsp_m_config *cfg = &upd->config; + struct fspm_arch_upd *arch = &upd->arch; + + arch->nvs_buffer_ptr = NULL; + prepare_mrc_cache(upd); + arch->stack_base = (void *)0xfef96000; + arch->boot_loader_tolum_size = 0; + + arch->boot_mode = FSP_BOOT_WITH_FULL_CONFIGURATION; + cfg->serial_debug_port_type = 2; + cfg->serial_debug_port_device = 2; + cfg->serial_debug_port_stride_size = 2; + cfg->serial_debug_port_address = 0; + + cfg->package = 1; + /* Don't enforce a memory size limit */ + cfg->memory_size_limit = 0; + cfg->low_memory_max_value = 2048; /* 2 GB */ + /* No restrictions on memory above 4GiB */ + cfg->high_memory_max_value = 0; + + /* Always default to attempt to use saved training data */ + cfg->disable_fast_boot = 0; + + const u8 *swizzle_data; + + swizzle_data = dev_read_u8_array_ptr(dev, "lpddr4-swizzle", + LP4_NUM_BYTE_LANES * + DQ_BITS_PER_DQS * + LP4_NUM_PHYS_CHANNELS); + if (!swizzle_data) + return log_msg_ret("Cannot read swizzel data", -EINVAL); + + setup_sdram(cfg, (struct lpddr4_swizzle_cfg *)swizzle_data); + + cfg->pre_mem_gpio_table_ptr = 0; + + cfg->profile = 0xb; + cfg->msg_level_mask = 0; + + /* other */ + cfg->skip_cse_rbp = 1; + cfg->periodic_retraining_disable = 0; + cfg->enable_s3_heci2 = 0; + + return 0; +} + +/* + * The FSP-M binary appears to break the SPI controller. It can be fixed by + * writing the BAR again, so do that here + */ +int fspm_done(struct udevice *dev) +{ + struct udevice *spi; + int ret; + + /* Don't probe the device, since that reads the BAR */ + ret = uclass_find_first_device(UCLASS_SPI, &spi); + if (ret) + return log_msg_ret("SPI", ret); + if (!spi) + return log_msg_ret("no SPI", -ENODEV); + + dm_pci_write_config32(spi, PCI_BASE_ADDRESS_0, + IOMAP_SPI_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY); + + return 0; +} diff --git a/arch/x86/cpu/apollolake/fsp_s.c b/arch/x86/cpu/apollolake/fsp_s.c new file mode 100644 index 0000000000..9804227f80 --- /dev/null +++ b/arch/x86/cpu/apollolake/fsp_s.c @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <acpi_s3.h> +#include <binman.h> +#include <dm.h> +#include <irq.h> +#include <asm/intel_pinctrl.h> +#include <asm/io.h> +#include <asm/intel_regs.h> +#include <asm/msr.h> +#include <asm/msr-index.h> +#include <asm/pci.h> +#include <asm/arch/cpu.h> +#include <asm/arch/systemagent.h> +#include <asm/arch/fsp/fsp_configs.h> +#include <asm/arch/fsp/fsp_s_upd.h> + +#define PCH_P2SB_E0 0xe0 +#define HIDE_BIT BIT(0) + +#define INTEL_GSPI_MAX 3 +#define INTEL_I2C_DEV_MAX 8 +#define MAX_USB2_PORTS 8 + +enum { + CHIPSET_LOCKDOWN_FSP = 0, /* FSP handles locking per UPDs */ + CHIPSET_LOCKDOWN_COREBOOT, /* coreboot handles locking */ +}; + +enum i2c_speed { + I2C_SPEED_STANDARD = 100000, + I2C_SPEED_FAST = 400000, + I2C_SPEED_FAST_PLUS = 1000000, + I2C_SPEED_HIGH = 3400000, + I2C_SPEED_FAST_ULTRA = 5000000, +}; + +/* + * Timing values are in units of clock period, with the clock speed + * provided by the SOC + * + * TODO(sjg@chromium.org): Connect this up to the I2C driver + */ +struct dw_i2c_speed_config { + enum i2c_speed speed; + /* SCL high and low period count */ + u16 scl_lcnt; + u16 scl_hcnt; + /* + * SDA hold time should be 300ns in standard and fast modes + * and long enough for deterministic logic level change in + * fast-plus and high speed modes. + * + * [15:0] SDA TX Hold Time + * [23:16] SDA RX Hold Time + */ + u32 sda_hold; +}; + +/* Serial IRQ control. SERIRQ_QUIET is the default (0) */ +enum serirq_mode { + SERIRQ_QUIET, + SERIRQ_CONTINUOUS, + SERIRQ_OFF, +}; + +/* + * This I2C controller has support for 3 independent speed configs but can + * support both FAST_PLUS and HIGH speeds through the same set of speed + * config registers. These are treated separately so the speed config values + * can be provided via ACPI to the OS. + */ +#define DW_I2C_SPEED_CONFIG_COUNT 4 + +struct dw_i2c_bus_config { + /* Bus should be enabled in TPL with temporary base */ + int early_init; + /* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */ + enum i2c_speed speed; + /* + * If rise_time_ns is non-zero the calculations for lcnt and hcnt + * registers take into account the times of the bus. However, if + * there is a match in speed_config those register values take + * precedence + */ + int rise_time_ns; + int fall_time_ns; + int data_hold_time_ns; + /* Specific bus speed configuration */ + struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT]; +}; + +struct gspi_cfg { + /* Bus speed in MHz */ + u32 speed_mhz; + /* Bus should be enabled prior to ramstage with temporary base */ + u8 early_init; +}; + +/* + * This structure will hold data required by common blocks. + * These are soc specific configurations which will be filled by soc. + * We'll fill this structure once during init and use the data in common block. + */ +struct soc_intel_common_config { + int chipset_lockdown; + struct gspi_cfg gspi[INTEL_GSPI_MAX]; + struct dw_i2c_bus_config i2c[INTEL_I2C_DEV_MAX]; +}; + +enum pnp_settings { + PNP_PERF, + PNP_POWER, + PNP_PERF_POWER, +}; + +struct usb2_eye_per_port { + u8 per_port_tx_pe_half; + u8 per_port_pe_txi_set; + u8 per_port_txi_set; + u8 hs_skew_sel; + u8 usb_tx_emphasis_en; + u8 per_port_rxi_set; + u8 hs_npre_drv_sel; + u8 override_en; +}; + +struct apl_config { + /* Common structure containing soc config data required by common code*/ + struct soc_intel_common_config common_soc_config; + + /* + * Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has + * four CLKREQ inputs, but six root ports. Root ports without an + * associated CLKREQ signal must be marked with "CLKREQ_DISABLED" + */ + u8 pcie_rp_clkreq_pin[MAX_PCIE_PORTS]; + + /* Enable/disable hot-plug for root ports (0 = disable, 1 = enable) */ + u8 pcie_rp_hotplug_enable[MAX_PCIE_PORTS]; + + /* De-emphasis enable configuration for each PCIe root port */ + u8 pcie_rp_deemphasis_enable[MAX_PCIE_PORTS]; + + /* + * [14:8] DDR mode Number of dealy elements.Each = 125pSec. + * [6:0] SDR mode Number of dealy elements.Each = 125pSec. + */ + u32 emmc_tx_cmd_cntl; + + /* + * [14:8] HS400 mode Number of dealy elements.Each = 125pSec. + * [6:0] SDR104/HS200 mode Number of dealy elements.Each = 125pSec. + */ + u32 emmc_tx_data_cntl1; + + /* + * [30:24] SDR50 mode Number of dealy elements.Each = 125pSec. + * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec. + * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec. + * [6:0] SDR12/Compatibility mode Number of dealy elements. + * Each = 125pSec. + */ + u32 emmc_tx_data_cntl2; + + /* + * [30:24] SDR50 mode Number of dealy elements.Each = 125pSec. + * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec. + * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec. + * [6:0] SDR12/Compatibility mode Number of dealy elements. + * Each = 125pSec. + */ + u32 emmc_rx_cmd_data_cntl1; + + /* + * [14:8] HS400 mode 1 Number of dealy elements.Each = 125pSec. + * [6:0] HS400 mode 2 Number of dealy elements.Each = 125pSec. + */ + u32 emmc_rx_strobe_cntl; + + /* + * [13:8] Auto Tuning mode Number of dealy elements.Each = 125pSec. + * [6:0] SDR104/HS200 Number of dealy elements.Each = 125pSec. + */ + u32 emmc_rx_cmd_data_cntl2; + + /* Select the eMMC max speed allowed */ + u32 emmc_host_max_speed; + + /* Specifies on which IRQ the SCI will internally appear */ + u32 sci_irq; + + /* Configure serial IRQ (SERIRQ) line */ + enum serirq_mode serirq_mode; + + /* Configure LPSS S0ix Enable */ + bool lpss_s0ix_enable; + + /* Enable DPTF support */ + bool dptf_enable; + + /* TCC activation offset value in degrees Celsius */ + int tcc_offset; + + /* + * Configure Audio clk gate and power gate + * IOSF-SB port ID 92 offset 0x530 [5] and [3] + */ + bool hdaudio_clk_gate_enable; + bool hdaudio_pwr_gate_enable; + bool hdaudio_bios_config_lockdown; + + /* SLP S3 minimum assertion width */ + int slp_s3_assertion_width_usecs; + + /* GPIO pin for PERST_0 */ + u32 prt0_gpio; + + /* USB2 eye diagram settings per port */ + struct usb2_eye_per_port usb2eye[MAX_USB2_PORTS]; + + /* GPIO SD card detect pin */ + unsigned int sdcard_cd_gpio; + + /* + * PRMRR size setting with three options + * 0x02000000 - 32MiB + * 0x04000000 - 64MiB + * 0x08000000 - 128MiB + */ + u32 PrmrrSize; + + /* + * Enable SGX feature. + * Enabling SGX feature is 2 step process, + * (1) set sgx_enable = 1 + * (2) set PrmrrSize to supported size + */ + bool sgx_enable; + + /* + * Select PNP Settings. + * (0) Performance, + * (1) Power + * (2) Power & Performance + */ + enum pnp_settings pnp_settings; + + /* + * PMIC PCH_PWROK delay configuration - IPC Configuration + * Upd for changing PCH_PWROK delay configuration : I2C_Slave_Address + * (31:24) + Register_Offset (23:16) + OR Value (15:8) + AND Value (7:0) + */ + u32 pmic_pmc_ipc_ctrl; + + /* + * Options to disable XHCI Link Compliance Mode. Default is FALSE to not + * disable Compliance Mode. Set TRUE to disable Compliance Mode. + * 0:FALSE(Default), 1:True. + */ + bool disable_compliance_mode; + + /* + * Options to change USB3 ModPhy setting for the Integrated Filter (IF) + * value. Default is 0 to not changing default IF value (0x12). Set + * value with the range from 0x01 to 0xff to change IF value. + */ + u32 mod_phy_if_value; + + /* + * Options to bump USB3 LDO voltage. Default is FALSE to not increasing + * LDO voltage. Set TRUE to increase LDO voltage with 40mV. + * 0:FALSE (default), 1:True. + */ + bool mod_phy_voltage_bump; + + /* + * Options to adjust PMIC Vdd2 voltage. Default is 0 to not adjusting + * the PMIC Vdd2 default voltage 1.20v. Upd for changing Vdd2 Voltage + * configuration: I2C_Slave_Address (31:23) + Register_Offset (23:16) + * + OR Value (15:8) + AND Value (7:0) through BUCK5_VID[3:2]: + * 00=1.10v, 01=1.15v, 10=1.24v, 11=1.20v (default). + */ + u32 pmic_vdd2_voltage; + + /* Option to enable VTD feature */ + bool enable_vtd; +}; + +static int get_config(struct udevice *dev, struct apl_config *apl) +{ + const u8 *ptr; + ofnode node; + u32 emmc[4]; + int ret; + + memset(apl, '\0', sizeof(*apl)); + + node = dev_read_subnode(dev, "fsp-s"); + if (!ofnode_valid(node)) + return log_msg_ret("fsp-s settings", -ENOENT); + + ptr = ofnode_read_u8_array_ptr(node, "pcie-rp-clkreq-pin", + MAX_PCIE_PORTS); + if (!ptr) + return log_msg_ret("pcie-rp-clkreq-pin", -EINVAL); + memcpy(apl->pcie_rp_clkreq_pin, ptr, MAX_PCIE_PORTS); + + ret = ofnode_read_u32(node, "prt0-gpio", &apl->prt0_gpio); + if (ret) + return log_msg_ret("prt0-gpio", ret); + ret = ofnode_read_u32(node, "sdcard-cd-gpio", &apl->sdcard_cd_gpio); + if (ret) + return log_msg_ret("sdcard-cd-gpio", ret); + + ret = ofnode_read_u32_array(node, "emmc", emmc, ARRAY_SIZE(emmc)); + if (ret) + return log_msg_ret("emmc", ret); + apl->emmc_tx_data_cntl1 = emmc[0]; + apl->emmc_tx_data_cntl2 = emmc[1]; + apl->emmc_rx_cmd_data_cntl1 = emmc[2]; + apl->emmc_rx_cmd_data_cntl2 = emmc[3]; + + apl->dptf_enable = ofnode_read_bool(node, "dptf-enable"); + + apl->hdaudio_clk_gate_enable = ofnode_read_bool(node, + "hdaudio-clk-gate-enable"); + apl->hdaudio_pwr_gate_enable = ofnode_read_bool(node, + "hdaudio-pwr-gate-enable"); + apl->hdaudio_bios_config_lockdown = ofnode_read_bool(node, + "hdaudio-bios-config-lockdown"); + apl->lpss_s0ix_enable = ofnode_read_bool(node, "lpss-s0ix-enable"); + + /* Santa */ + apl->usb2eye[1].per_port_pe_txi_set = 7; + apl->usb2eye[1].per_port_txi_set = 2; + + return 0; +} + +static void apl_fsp_silicon_init_params_cb(struct apl_config *apl, + struct fsp_s_config *cfg) +{ + u8 port; + + for (port = 0; port < MAX_USB2_PORTS; port++) { + if (apl->usb2eye[port].per_port_tx_pe_half) + cfg->port_usb20_per_port_tx_pe_half[port] = + apl->usb2eye[port].per_port_tx_pe_half; + + if (apl->usb2eye[port].per_port_pe_txi_set) + cfg->port_usb20_per_port_pe_txi_set[port] = + apl->usb2eye[port].per_port_pe_txi_set; + + if (apl->usb2eye[port].per_port_txi_set) + cfg->port_usb20_per_port_txi_set[port] = + apl->usb2eye[port].per_port_txi_set; + + if (apl->usb2eye[port].hs_skew_sel) + cfg->port_usb20_hs_skew_sel[port] = + apl->usb2eye[port].hs_skew_sel; + + if (apl->usb2eye[port].usb_tx_emphasis_en) + cfg->port_usb20_i_usb_tx_emphasis_en[port] = + apl->usb2eye[port].usb_tx_emphasis_en; + + if (apl->usb2eye[port].per_port_rxi_set) + cfg->port_usb20_per_port_rxi_set[port] = + apl->usb2eye[port].per_port_rxi_set; + + if (apl->usb2eye[port].hs_npre_drv_sel) + cfg->port_usb20_hs_npre_drv_sel[port] = + apl->usb2eye[port].hs_npre_drv_sel; + } +} + +int fsps_update_config(struct udevice *dev, ulong rom_offset, + struct fsps_upd *upd) +{ + struct fsp_s_config *cfg = &upd->config; + struct apl_config *apl; + struct binman_entry vbt; + void *buf; + int ret; + + ret = binman_entry_find("intel-vbt", &vbt); + if (ret) + return log_msg_ret("Cannot find VBT", ret); + vbt.image_pos += rom_offset; + buf = malloc(vbt.size); + if (!buf) + return log_msg_ret("Alloc VBT", -ENOMEM); + + /* + * Load VBT before devicetree-specific config. This only supports + * memory-mapped SPI at present. + */ + bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi"); + memcpy(buf, (void *)vbt.image_pos, vbt.size); + bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI); + if (*(u32 *)buf != VBT_SIGNATURE) + return log_msg_ret("VBT signature", -EINVAL); + cfg->graphics_config_ptr = (ulong)buf; + + apl = malloc(sizeof(*apl)); + if (!apl) + return log_msg_ret("config", -ENOMEM); + get_config(dev, apl); + + cfg->ish_enable = 0; + cfg->enable_sata = 0; + cfg->pcie_root_port_en[2] = 0; + cfg->pcie_rp_hot_plug[2] = 0; + cfg->pcie_root_port_en[3] = 0; + cfg->pcie_rp_hot_plug[3] = 0; + cfg->pcie_root_port_en[4] = 0; + cfg->pcie_rp_hot_plug[4] = 0; + cfg->pcie_root_port_en[5] = 0; + cfg->pcie_rp_hot_plug[5] = 0; + cfg->pcie_root_port_en[1] = 0; + cfg->pcie_rp_hot_plug[1] = 0; + cfg->usb_otg = 0; + cfg->i2c6_enable = 0; + cfg->i2c7_enable = 0; + cfg->hsuart3_enable = 0; + cfg->spi1_enable = 0; + cfg->spi2_enable = 0; + cfg->sdio_enabled = 0; + + memcpy(cfg->pcie_rp_clk_req_number, apl->pcie_rp_clkreq_pin, + sizeof(cfg->pcie_rp_clk_req_number)); + + memcpy(cfg->pcie_rp_hot_plug, apl->pcie_rp_hotplug_enable, + sizeof(cfg->pcie_rp_hot_plug)); + + switch (apl->serirq_mode) { + case SERIRQ_QUIET: + cfg->sirq_enable = 1; + cfg->sirq_mode = 0; + break; + case SERIRQ_CONTINUOUS: + cfg->sirq_enable = 1; + cfg->sirq_mode = 1; + break; + case SERIRQ_OFF: + default: + cfg->sirq_enable = 0; + break; + } + + if (apl->emmc_tx_cmd_cntl) + cfg->emmc_tx_cmd_cntl = apl->emmc_tx_cmd_cntl; + if (apl->emmc_tx_data_cntl1) + cfg->emmc_tx_data_cntl1 = apl->emmc_tx_data_cntl1; + if (apl->emmc_tx_data_cntl2) + cfg->emmc_tx_data_cntl2 = apl->emmc_tx_data_cntl2; + if (apl->emmc_rx_cmd_data_cntl1) + cfg->emmc_rx_cmd_data_cntl1 = apl->emmc_rx_cmd_data_cntl1; + if (apl->emmc_rx_strobe_cntl) + cfg->emmc_rx_strobe_cntl = apl->emmc_rx_strobe_cntl; + if (apl->emmc_rx_cmd_data_cntl2) + cfg->emmc_rx_cmd_data_cntl2 = apl->emmc_rx_cmd_data_cntl2; + if (apl->emmc_host_max_speed) + cfg->e_mmc_host_max_speed = apl->emmc_host_max_speed; + + cfg->lpss_s0ix_enable = apl->lpss_s0ix_enable; + + cfg->skip_mp_init = true; + + /* Disable setting of EISS bit in FSP */ + cfg->spi_eiss = 0; + + /* Disable FSP from locking access to the RTC NVRAM */ + cfg->rtc_lock = 0; + + /* Enable Audio clk gate and power gate */ + cfg->hd_audio_clk_gate = apl->hdaudio_clk_gate_enable; + cfg->hd_audio_pwr_gate = apl->hdaudio_pwr_gate_enable; + /* Bios config lockdown Audio clk and power gate */ + cfg->bios_cfg_lock_down = apl->hdaudio_bios_config_lockdown; + apl_fsp_silicon_init_params_cb(apl, cfg); + + cfg->usb_otg = true; + cfg->vtd_enable = apl->enable_vtd; + + return 0; +} + +static void p2sb_set_hide_bit(pci_dev_t dev, int hide) +{ + pci_x86_clrset_config(dev, PCH_P2SB_E0 + 1, HIDE_BIT, + hide ? HIDE_BIT : 0, PCI_SIZE_8); +} + +/* Configure package power limits */ +static int set_power_limits(struct udevice *dev) +{ + msr_t rapl_msr_reg, limit; + u32 power_unit; + u32 tdp, min_power, max_power; + u32 pl2_val; + u32 override_tdp[2]; + int ret; + + /* Get units */ + rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT); + power_unit = 1 << (rapl_msr_reg.lo & 0xf); + + /* Get power defaults for this SKU */ + rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU); + tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK; + pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK; + min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK; + max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK; + + if (min_power > 0 && tdp < min_power) + tdp = min_power; + + if (max_power > 0 && tdp > max_power) + tdp = max_power; + + ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp, + ARRAY_SIZE(override_tdp)); + if (ret) + return log_msg_ret("tdp-pl-override-mw", ret); + + /* Set PL1 override value */ + if (override_tdp[0]) + tdp = override_tdp[0] * power_unit / 1000; + + /* Set PL2 override value */ + if (override_tdp[1]) + pl2_val = override_tdp[1] * power_unit / 1000; + + /* Set long term power limit to TDP */ + limit.lo = tdp & PKG_POWER_LIMIT_MASK; + /* Set PL1 Pkg Power clamp bit */ + limit.lo |= PKG_POWER_LIMIT_CLAMP; + + limit.lo |= PKG_POWER_LIMIT_EN; + limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT & + PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT; + + /* Set short term power limit PL2 */ + limit.hi = pl2_val & PKG_POWER_LIMIT_MASK; + limit.hi |= PKG_POWER_LIMIT_EN; + + /* Program package power limits in RAPL MSR */ + msr_write(MSR_PKG_POWER_LIMIT, limit); + log_info("RAPL PL1 %d.%dW\n", tdp / power_unit, + 100 * (tdp % power_unit) / power_unit); + log_info("RAPL PL2 %d.%dW\n", pl2_val / power_unit, + 100 * (pl2_val % power_unit) / power_unit); + + /* + * Sett RAPL MMIO register for Power limits. RAPL driver is using MSR + * instead of MMIO, so disable LIMIT_EN bit for MMIO + */ + writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL)); + writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4)); + + return 0; +} + +int p2sb_unhide(void) +{ + pci_dev_t dev = PCI_BDF(0, 0xd, 0); + ulong val; + + p2sb_set_hide_bit(dev, 0); + + pci_x86_read_config(dev, PCI_VENDOR_ID, &val, PCI_SIZE_16); + + if (val != PCI_VENDOR_ID_INTEL) + return log_msg_ret("p2sb unhide", -EIO); + + return 0; +} + +/* Overwrites the SCI IRQ if another IRQ number is given by device tree */ +static void set_sci_irq(void) +{ + /* Skip this for now */ +} + +int arch_fsps_preinit(void) +{ + struct udevice *itss; + int ret; + + ret = uclass_first_device_err(UCLASS_IRQ, &itss); + if (ret) + return log_msg_ret("no itss", ret); + /* + * Snapshot the current GPIO IRQ polarities. FSP is setting a default + * policy that doesn't honour boards' requirements + */ + irq_snapshot_polarities(itss); + + /* + * Clear the GPI interrupt status and enable registers. These + * registers do not get reset to default state when booting from S5. + */ + ret = pinctrl_gpi_clear_int_cfg(); + if (ret) + return log_msg_ret("gpi_clear", ret); + + return 0; +} + +int arch_fsp_init_r(void) +{ +#ifdef CONFIG_HAVE_ACPI_RESUME + bool s3wake = gd->arch.prev_sleep_state == ACPI_S3; +#else + bool s3wake = false; +#endif + struct udevice *dev, *itss; + int ret; + + /* + * This must be called before any devices are probed. Put any probing + * into arch_fsps_preinit() above. + * + * We don't use CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH here since it will + * force PCI to be probed. + */ + ret = fsp_silicon_init(s3wake, false); + if (ret) + return ret; + + ret = uclass_first_device_err(UCLASS_IRQ, &itss); + if (ret) + return log_msg_ret("no itss", ret); + /* Restore GPIO IRQ polarities back to previous settings */ + irq_restore_polarities(itss); + + /* soc_init() */ + ret = p2sb_unhide(); + if (ret) + return log_msg_ret("unhide p2sb", ret); + + /* Set RAPL MSR for Package power limits*/ + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); + if (ret) + return log_msg_ret("Cannot get northbridge", ret); + set_power_limits(dev); + + /* + * FSP-S routes SCI to IRQ 9. With the help of this function you can + * select another IRQ for SCI. + */ + set_sci_irq(); + + return 0; +}

On Mon, Dec 9, 2019 at 8:42 AM Simon Glass sjg@chromium.org wrote:
The memory and silicon init parts of the FSP need support code to work. Add this for Apollo Lake.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Drop mention of devicetree for VTD feature
- Drop mention of ramstage
- Fix various coding style problems
- Make BOOT_FROM_FAST_SPI_FLASH a Kconfig option
- Use 'No SPI' instead of 'SPI2' as a debug message
Changes in v5:
- Allocate the FSP-S data instead of using the stack
- Rename APOLLOLAKE_USB2_PORT_MAX
Changes in v4:
- Adjust the comment for struct dw_i2c_speed_config
- Rename arch_fsp_s_preinit() to arch_fsps_preinit()
- Switch over to use pinctrl for pad init/config
- Tidy up mixed case in FSP code
- apollolake -> Apollo Lake
Changes in v3:
- Add bootstage timing for reading vbt
- Add fspm_done() hook to handle FSP-S wierdness (it breaks SPI flash)
- Don't allow BOOT_FROM_FAST_SPI_FLASH with FSP-S
- Set boot_loader_tolum_size to 0
- Use the IRQ uclass instead of ITSS
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 6 + arch/x86/cpu/apollolake/fsp_m.c | 210 ++++++++++ arch/x86/cpu/apollolake/fsp_s.c | 661 +++++++++++++++++++++++++++++++ 3 files changed, 877 insertions(+) create mode 100644 arch/x86/cpu/apollolake/fsp_m.c create mode 100644 arch/x86/cpu/apollolake/fsp_s.c
applied to u-boot-x86/next, thanks!

Add support for coral which is a range of Apollo Lake-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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v7: - Add the new documentation to the index file
Changes in v6: - Add a comment about the need for board_run_command() - Use generic gpio compatible string
Changes in v5: - Add gpio-controller to GPIO nodes - Comment out GPIOs in the fsp_s node since we don't use them yet - Correct CPU ACPI IDs - Use a define for ACPI base address
Changes in v4: - Add u-boot,skip-auto-config-until-reloc property to PCI - Drop duplicate commit 'Create a new sandbox_pci_read_bar() function' - New GPIO driver binding - Set up LPC pads early - Switch over to use pinctrl for pad init/config - Update documentation with more detailed memory map - Use hyphen for device-tree properties - apollolake -> Apollo Lake
Changes in v3: - Ad FSP-S support - Add CONFIG_TPL_X86_ASSUME_CPUID to reduce code size - Add Chrome OS EC support - Add a proper SPI node and make the SPI flash node a child - Add bootstage support - Add more documentation - Add spi alias in device tree - Disable the bootcommand since it does nothing useful on coral - Don't enable SPI flash in TPL by default - Drop CONFIG_SPL_NET_SUPPORT - Drop patch '86: timer: Reduce timer code size in TPL on Intel CPUs' - Drop patch 'dm: core: Don't include ofnode functions with of-platdata' - Drop patch 'spi: sandbox: Add a test driver for sandbox SPI flash' - Drop patch 'spl: Allow SPL/TPL to use of-platdata without libfdt' - Drop patch 'x86: apollolake: Add definitions for the Intel Fast SPI interface' - Drop patch 'x86: timer: Set up the timer in timer_early_get_count()' - Enable video and USB3 - Reduce amount of early-pad data in TPL - Tidy up the pad settings in the device tree - Use a zero-based tsc timer
Changes in v2: None
arch/x86/dts/Makefile | 1 + arch/x86/dts/chromebook_coral.dts | 831 ++++++++++++++++++++++ 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 | 19 + configs/chromebook_coral_defconfig | 102 +++ doc/board/google/chromebook_coral.rst | 241 +++++++ doc/board/google/index.rst | 1 + include/configs/chromebook_coral.h | 32 + 11 files changed, 1296 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 d4bdf62be6..be209aaaf8 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 0000000000..24fcbb5063 --- /dev/null +++ b/arch/x86/dts/chromebook_coral.dts @@ -0,0 +1,831 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/dts-v1/; + +#include <dt-bindings/gpio/x86-gpio.h> + +/include/ "skeleton.dtsi" +/include/ "keyboard.dtsi" +/include/ "reset.dtsi" +/include/ "rtc.dtsi" +/include/ "tsc_timer.dtsi" + +#ifdef CONFIG_CHROMEOS +#include "chromeos-x86.dtsi" +#include "flashmap-x86-ro.dtsi" +#include "flashmap-16mb-rw.dtsi" +#endif + +#include <asm/intel_pinctrl_defs.h> +#include <asm/arch-apollolake/cpu.h> +#include <asm/arch-apollolake/gpio.h> +#include <asm/arch-apollolake/iomap.h> +#include <asm/arch-apollolake/pm.h> + +/ { + model = "Google Coral"; + compatible = "google,coral", "intel,apollolake"; + + aliases { + cros-ec0 = &cros_ec; + fsp = &fsp_s; + spi0 = &spi; + }; + + config { + silent_console = <0>; + }; + + chosen { + stdout-path = &serial; + }; + + cpus { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + u-boot,dm-pre-reloc; + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <0>; + intel,apic-id = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <1>; + intel,apic-id = <2>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <2>; + intel,apic-id = <4>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "intel,apl-cpu"; + reg = <3>; + intel,apic-id = <6>; + }; + + }; + + keyboard { + intel,duplicate-por; + }; + + pci { + compatible = "pci-x86"; + #address-cells = <3>; + #size-cells = <2>; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0 0x10000000 + 0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000 + 0x01000000 0x0 0x1000 0x1000 0 0xefff>; + u-boot,skip-auto-config-until-reloc; + + host_bridge: host-bridge@0,0 { + u-boot,dm-pre-reloc; + reg = <0x00000000 0 0 0 0>; + compatible = "intel,apl-hostbridge"; + pciex-region-size = <0x10000000>; + /* + * Parameters used by the FSP-S binary blob. This is + * really unfortunate since these parameters mostly + * relate to drivers but we need them in one place. We + * could put them in the driver nodes easily, but then + * would have to scan each node to find them. So just + * dump them here for now. + */ + fsp_s: fsp-s { + }; + }; + + punit@0,1 { + u-boot,dm-pre-reloc; + reg = <0x00000800 0 0 0 0>; + compatible = "intel,apl-punit"; + }; + + p2sb: p2sb@d,0 { + u-boot,dm-pre-reloc; + reg = <0x02006810 0 0 0 0>; + compatible = "intel,apl-p2sb"; + early-regs = <IOMAP_P2SB_BAR 0x100000>; + + n { + compatible = "intel,apl-pinctrl"; + u-boot,dm-pre-reloc; + intel,p2sb-port-id = <PID_GPIO_N>; + gpio_n: gpio-n { + compatible = "intel,gpio"; + u-boot,dm-pre-reloc; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + nw { + u-boot,dm-pre-reloc; + compatible = "intel,apl-pinctrl"; + intel,p2sb-port-id = <PID_GPIO_NW>; + #gpio-cells = <2>; + gpio_nw: gpio-nw { + compatible = "intel,gpio"; + u-boot,dm-pre-reloc; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + w { + u-boot,dm-pre-reloc; + compatible = "intel,apl-pinctrl"; + intel,p2sb-port-id = <PID_GPIO_W>; + #gpio-cells = <2>; + gpio_w: gpio-w { + compatible = "intel,gpio"; + u-boot,dm-pre-reloc; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + sw { + u-boot,dm-pre-reloc; + compatible = "intel,apl-pinctrl"; + intel,p2sb-port-id = <PID_GPIO_SW>; + #gpio-cells = <2>; + gpio_sw: gpio-sw { + compatible = "intel,gpio"; + u-boot,dm-pre-reloc; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + itss { + u-boot,dm-pre-reloc; + compatible = "intel,apl-itss"; + intel,p2sb-port-id = <PID_ITSS>; + intel,pmc-routes = < + PMC_GPE_SW_31_0 GPIO_GPE_SW_31_0 + PMC_GPE_SW_63_32 GPIO_GPE_SW_63_32 + PMC_GPE_NW_31_0 GPIO_GPE_NW_31_0 + PMC_GPE_NW_63_32 GPIO_GPE_NW_63_32 + PMC_GPE_NW_95_64 GPIO_GPE_NW_95_64 + PMC_GPE_N_31_0 GPIO_GPE_N_31_0 + PMC_GPE_N_63_32 GPIO_GPE_N_63_32 + PMC_GPE_W_31_0 GPIO_GPE_W_31_0>; + }; + }; + + pmc@d,1 { + u-boot,dm-pre-reloc; + reg = <0x6900 0 0 0 0>; + + /* + * Values for BAR0, BAR2 and ACPI_BASE for when PCI + * auto-configure is not available + */ + early-regs = <0xfe042000 0x2000 + 0xfe044000 0x2000 + IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>; + compatible = "intel,apl-pmc"; + gpe0-dwx-mask = <0xf>; + gpe0-dwx-shift-base = <4>; + + /* + * GPE configuration + * Note that GPE events called out in ASL code rely on + * this route, i.e., if this route changes then the + * affected GPE * offset bits also need to be changed. + * This sets the PMC register GPE_CFG fields. + */ + gpe0-dw = <PMC_GPE_N_31_0 + PMC_GPE_N_63_32 + PMC_GPE_SW_31_0>; + gpe0-sts = <0x20>; + gpe0-en = <0x30>; + }; + + spi: fast-spi@d,2 { + u-boot,dm-pre-reloc; + reg = <0x02006a10 0 0 0 0>; + #address-cells = <1>; + #size-cells = <0>; + compatible = "intel,fast-spi"; + early-regs = <IOMAP_SPI_BASE 0x1000>; + intel,hardware-seq = <1>; + + fwstore_spi: spi-flash@0 { + #size-cells = <1>; + #address-cells = <1>; + u-boot,dm-pre-reloc; + reg = <0>; + compatible = "winbond,w25q128fw", + "jedec,spi-nor"; + rw-mrc-cache { + label = "rw-mrc-cache"; + reg = <0x008e0000 0x00010000>; + u-boot,dm-pre-reloc; + }; + rw-var-mrc-cache { + label = "rw-mrc-cache"; + reg = <0x008f0000 0x0001000>; + u-boot,dm-pre-reloc; + }; + }; + }; + + serial: serial@18,2 { + reg = <0x0200c210 0 0 0 0>; + u-boot,dm-pre-reloc; + compatible = "intel,apl-ns16550"; + early-regs = <0xde000000 0x20>; + reg-shift = <2>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; + + pch: pch@1f,0 { + reg = <0x0000f800 0 0 0 0>; + compatible = "intel,apl-pch"; + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + + lpc { + compatible = "intel,apl-lpc"; + #address-cells = <1>; + #size-cells = <0>; + u-boot,dm-pre-reloc; + cros_ec: cros-ec { + u-boot,dm-pre-reloc; + compatible = "google,cros-ec-lpc"; + reg = <0x204 1 0x200 1 0x880 0x80>; + + /* + * Describes the flash memory within + * the EC + */ + #address-cells = <1>; + #size-cells = <1>; + flash@8000000 { + reg = <0x08000000 0x20000>; + erase-value = <0xff>; + }; + }; + }; + }; + }; + +}; + +&host_bridge { + /* + * PL1 override 12000 mW: the energy calculation is wrong with the + * current VR solution. Experiments show that SoC TDP max (6W) can be + * reached when RAPL PL1 is set to 12W. Set RAPL PL2 to 15W. + */ + tdp-pl-override-mw = <12000 15000>; + + early-pads = < + /* These two are for the debug UART */ + GPIO_46 /* UART2 RX */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE) + + GPIO_47 /* UART2 TX */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_NATIVE | PAD_CFG1_IOSSTATE_TX_LAST_RXE) + + GPIO_75 /* I2S1_BCLK -- PCH_WP */ + (PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_20K | PAD_CFG1_IOSSTATE_TXD_RXE) + + /* I2C2 - TPM */ + GPIO_128 /* LPSS_I2C2_SDA */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE) + GPIO_129 /* LPSS_I2C2_SCL */ + (PAD_CFG0_MODE_NF1 | PAD_CFG0_LOGICAL_RESET_DEEP) + (PAD_CFG1_PULL_UP_2K | PAD_CFG1_IOSSTATE_TX_LAST_RXE) + GPIO_28 /* TPM IRQ */ + (PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP | + PAD_CFG0_TX_DISABLE | PAD_CFG0_ROUTE_IOAPIC | + PAD_CFG0_TRIG_LEVEL | PAD_CFG0_RX_POL_INVERT) + (PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TXD_RXE) + + /* + * WLAN_PE_RST - default to deasserted just in case FSP + * misbehaves + */ + GPIO_122 /* SIO_SPI_2_RXD */ + (PAD_CFG0_MODE_GPIO | PAD_CFG0_LOGICAL_RESET_DEEP | + PAD_CFG0_RX_DISABLE | 0) + (PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TX_LAST_RXE) + + /* LPC */ + PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1) /* LPC_SERIRQ */ + PAD_CFG_NF(LPC_CLKOUT0, NONE, DEEP, NF1) /* LPC_CLKOUT0 */ + PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1) + PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1) /* LPC_AD0 */ + PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1) /* LPC_AD1 */ + PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1) /* LPC_AD2 */ + PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1) /* LPC_AD3 */ + PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */ + PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */ + >; + + lpddr4-swizzle = /bits/ 8 < + /* LP4_PHYS_CH0A */ + + /* DQA[0:7] pins of LPDDR4 module */ + 6 7 5 4 3 1 0 2 + /* DQA[8:15] pins of LPDDR4 module */ + 12 10 11 13 14 8 9 15 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 16 22 23 20 18 17 19 21 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 30 28 29 25 24 26 27 31 + + /* LP4_PHYS_CH0B */ + /* DQA[0:7] pins of LPDDR4 module */ + 7 3 5 2 6 0 1 4 + /* DQA[8:15] pins of LPDDR4 module */ + 9 14 12 13 10 11 8 15 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 20 22 23 16 19 17 18 21 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 28 24 26 27 29 30 31 25 + + /* LP4_PHYS_CH1A */ + + /* DQA[0:7] pins of LPDDR4 module */ + 2 1 6 7 5 4 3 0 + /* DQA[8:15] pins of LPDDR4 module */ + 11 10 8 9 12 15 13 14 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 17 23 19 16 21 22 20 18 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 31 29 26 25 28 27 24 30 + + /* LP4_PHYS_CH1B */ + + /* DQA[0:7] pins of LPDDR4 module */ + 4 3 7 5 6 1 0 2 + /* DQA[8:15] pins of LPDDR4 module */ + 15 9 8 11 14 13 12 10 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 20 23 22 21 18 19 16 17 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 25 28 30 31 26 27 24 29>; +}; + +&fsp_s { + u-boot,dm-pre-proper; + + /* Disable unused clkreq of PCIe root ports */ + pcie-rp-clkreq-pin = /bits/ 8 <0 /* wifi/bt */ + CLKREQ_DISABLED + CLKREQ_DISABLED + CLKREQ_DISABLED + CLKREQ_DISABLED + CLKREQ_DISABLED>; + + /* + * GPIO for PERST_0 + * If the Board has PERST_0 signal, assign the GPIO + * If the Board does not have PERST_0, assign GPIO_PRT0_UDEF + * + * This are not used yet, so comment them out for now. + * + * prt0-gpio = <GPIO_122>; + * + * GPIO for SD card detect + * sdcard-cd-gpio = <GPIO_177>; + */ + + /* + * Order is emmc-tx-data-cntl1, emmc-tx-data-cntl2, + * emmc-rx-cmd-data-cntl1, emmc-rx-cmd-data-cntl2 + * + * EMMC TX DATA Delay 1 + * Refer to EDS-Vol2-22.3 + * [14:8] steps of delay for HS400, each 125ps + * [6:0] steps of delay for SDR104/HS200, each 125ps + + /* + * EMMC TX DATA Delay 2 + * Refer to EDS-Vol2-22.3. + * [30:24] steps of delay for SDR50, each 125ps + * [22:16] steps of delay for DDR50, each 125ps + * [14:8] steps of delay for SDR25/HS50, each 125ps + * [6:0] steps of delay for SDR12, each 125ps + */ + + /* + * EMMC RX CMD/DATA Delay 1 + * Refer to EDS-Vol2-22.3. + * [30:24] steps of delay for SDR50, each 125ps + * [22:16] steps of delay for DDR50, each 125ps + * [14:8] steps of delay for SDR25/HS50, each 125ps + * [6:0] steps of delay for SDR12, each 125ps + */ + + /* + * EMMC RX CMD/DATA Delay 2 + * Refer to EDS-Vol2-22.3. + * [17:16] stands for Rx Clock before Output Buffer + * [14:8] steps of delay for Auto Tuning Mode, each 125ps + * [6:0] steps of delay for HS200, each 125ps + */ + emmc = <0x0c16 0x28162828 0x00181717 0x10008>; + + /* Enable DPTF */ + dptf-enable; + + /* Enable Audio Clock and Power gating */ + hdaudio-clk-gate-enable; + hdaudio-pwr-gate-enable; + hdaudio-bios-config-lockdown; + + /* Enable lpss s0ix */ + lpss-s0ix-enable; + + /* + * TODO(sjg@chromium.org): Move this to the I2C nodes + * Intel Common SoC Config + *+-------------------+---------------------------+ + *| Field | Value | + *+-------------------+---------------------------+ + *| I2C0 | Audio | + *| I2C2 | TPM | + *| I2C3 | Touchscreen | + *| I2C4 | Trackpad | + *| I2C5 | Digitizer | + *+-------------------+---------------------------+ + * + common_soc_config" = "{ + .i2c[0] = { + .speed = I2C_SPEED_FAST, + .rise-time-ns = 104, + .fall-time-ns = 52, + }, + .i2c[2] = { + .early_init = 1, + .speed = I2C_SPEED_FAST, + .rise-time-ns = 57, + .fall-time-ns = 28, + }, + .i2c[3] = { + .speed = I2C_SPEED_FAST, + .rise-time-ns = 76, + .fall-time-ns = 164, + }, + .i2c[4] = { + .speed = I2C_SPEED_FAST, + .rise-time-ns = 114, + .fall-time-ns = 164, + .data_hold_time_ns = 350, + }, + .i2c[5] = { + .speed = I2C_SPEED_FAST, + .rise-time-ns = 152, + .fall-time-ns = 30, + }, + }" + */ + + /* Minimum SLP S3 assertion width 28ms */ + slp-s3-assertion-width-usecs = <28000>; + + pads = < + /* PCIE_WAKE[0:3]_N */ + PAD_CFG_GPI_SCI_LOW(GPIO_205, UP_20K, DEEP, EDGE_SINGLE) /* WLAN */ + PAD_CFG_GPI(GPIO_206, UP_20K, DEEP) /* Unused */ + PAD_CFG_GPI(GPIO_207, UP_20K, DEEP) /* Unused */ + PAD_CFG_GPI(GPIO_208, UP_20K, DEEP) /* Unused */ + + /* EMMC interface */ + PAD_CFG_NF(GPIO_156, DN_20K, DEEP, NF1) /* EMMC_CLK */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_157, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D0 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_158, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D1 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_159, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D2 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_160, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D3 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_161, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D4 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_162, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D5 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_163, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D6 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_164, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_D7 */ + PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_165, UP_20K, DEEP, NF1, HIZCRX1, DISPUPD) /* EMMC_CMD */ + PAD_CFG_NF(GPIO_182, DN_20K, DEEP, NF1) /* EMMC_RCLK */ + + /* SDIO -- unused */ + PAD_CFG_GPI(GPIO_166, UP_20K, DEEP) /* SDIO_CLK */ + PAD_CFG_GPI(GPIO_167, UP_20K, DEEP) /* SDIO_D0 */ + /* Configure SDIO to enable power gating */ + PAD_CFG_NF(GPIO_168, UP_20K, DEEP, NF1) /* SDIO_D1 */ + PAD_CFG_GPI(GPIO_169, UP_20K, DEEP) /* SDIO_D2 */ + PAD_CFG_GPI(GPIO_170, UP_20K, DEEP) /* SDIO_D3 */ + PAD_CFG_GPI(GPIO_171, UP_20K, DEEP) /* SDIO_CMD */ + + /* SDCARD */ + /* Pull down clock by 20K */ + PAD_CFG_NF(GPIO_172, DN_20K, DEEP, NF1) /* SDCARD_CLK */ + PAD_CFG_NF(GPIO_173, UP_20K, DEEP, NF1) /* SDCARD_D0 */ + PAD_CFG_NF(GPIO_174, UP_20K, DEEP, NF1) /* SDCARD_D1 */ + PAD_CFG_NF(GPIO_175, UP_20K, DEEP, NF1) /* SDCARD_D2 */ + PAD_CFG_NF(GPIO_176, UP_20K, DEEP, NF1) /* SDCARD_D3 */ + /* Card detect is active LOW with external pull up */ + PAD_CFG_NF(GPIO_177, NONE, DEEP, NF1) /* SDCARD_CD_N */ + PAD_CFG_NF(GPIO_178, UP_20K, DEEP, NF1) /* SDCARD_CMD */ + /* CLK feedback, internal signal, needs 20K pull down */ + PAD_CFG_NF(GPIO_179, DN_20K, DEEP, NF1) /* SDCARD_CLK_FB */ + /* No h/w write proect for uSD cards, pull down by 20K */ + PAD_CFG_NF(GPIO_186, DN_20K, DEEP, NF1) /* SDCARD_LVL_WP */ + /* EN_SD_SOCKET_PWR_L for SD slot power control. Default on */ + PAD_CFG_GPO(GPIO_183, 0, DEEP) /* SDIO_PWR_DOWN_N */ + + /* SMBus -- unused */ + PAD_CFG_GPI(SMB_ALERTB, UP_20K, DEEP) /* SMB_ALERT _N */ + PAD_CFG_GPI(SMB_CLK, UP_20K, DEEP) /* SMB_CLK */ + PAD_CFG_GPI(SMB_DATA, UP_20K, DEEP) /* SMB_DATA */ + + /* LPC */ + PAD_CFG_NF(LPC_ILB_SERIRQ, UP_20K, DEEP, NF1) /* LPC_SERIRQ */ + PAD_CFG_NF(LPC_CLKOUT0, NONE, DEEP, NF1) /* LPC_CLKOUT0 */ + PAD_CFG_NF(LPC_CLKOUT1, UP_20K, DEEP, NF1) + PAD_CFG_NF(LPC_AD0, UP_20K, DEEP, NF1) /* LPC_AD0 */ + PAD_CFG_NF(LPC_AD1, UP_20K, DEEP, NF1) /* LPC_AD1 */ + PAD_CFG_NF(LPC_AD2, UP_20K, DEEP, NF1) /* LPC_AD2 */ + PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1) /* LPC_AD3 */ + PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */ + PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */ + + /* I2C0 - Audio */ + PAD_CFG_NF(GPIO_124, UP_2K, DEEP, NF1) /* LPSS_I2C0_SDA */ + PAD_CFG_NF(GPIO_125, UP_2K, DEEP, NF1) /* LPSS_I2C0_SCL */ + + /* I2C1 - NFC with external pulls */ + PAD_CFG_NF(GPIO_126, NONE, DEEP, NF1) /* LPSS_I2C1_SDA */ + PAD_CFG_NF(GPIO_127, NONE, DEEP, NF1) /* LPSS_I2C1_SCL */ + + /* I2C2 - TPM */ + PAD_CFG_NF(GPIO_128, UP_2K, DEEP, NF1) /* LPSS_I2C2_SDA */ + PAD_CFG_NF(GPIO_129, UP_2K, DEEP, NF1) /* LPSS_I2C2_SCL */ + + /* I2C3 - touch */ + PAD_CFG_NF(GPIO_130, UP_2K, DEEP, NF1) /* LPSS_I2C3_SDA */ + PAD_CFG_NF(GPIO_131, UP_2K, DEEP, NF1) /* LPSS_I2C3_SCL */ + + /* I2C4 - trackpad */ + /* LPSS_I2C4_SDA */ + PAD_CFG_NF_IOSSTATE(GPIO_132, UP_2K, DEEP, NF1, HIZCRX1) + /* LPSS_I2C4_SCL */ + PAD_CFG_NF_IOSSTATE(GPIO_133, UP_2K, DEEP, NF1, HIZCRX1) + + /* I2C5 -- pen with external pulls */ + PAD_CFG_NF(GPIO_134, NONE, DEEP, NF1) /* LPSS_I2C5_SDA */ + PAD_CFG_NF(GPIO_135, NONE, DEEP, NF1) /* LPSS_I2C5_SCL */ + + /* I2C6-7 -- unused */ + PAD_CFG_GPI(GPIO_136, UP_20K, DEEP) /* LPSS_I2C6_SDA */ + PAD_CFG_GPI(GPIO_137, UP_20K, DEEP) /* LPSS_I2C6_SCL */ + PAD_CFG_GPI(GPIO_138, UP_20K, DEEP) /* LPSS_I2C7_SDA */ + PAD_CFG_GPI(GPIO_139, UP_20K, DEEP) /* LPSS_I2C7_SCL */ + + /* Audio Amp - I2S6 */ + PAD_CFG_NF(GPIO_146, NATIVE, DEEP, NF2) /* ISH_GPIO_0 - I2S6_BCLK */ + PAD_CFG_NF(GPIO_147, NATIVE, DEEP, NF2) /* ISH_GPIO_1 - I2S6_WS_SYNC */ + PAD_CFG_GPI(GPIO_148, UP_20K, DEEP) /* ISH_GPIO_2 - unused */ + PAD_CFG_NF(GPIO_149, NATIVE, DEEP, NF2) /* ISH_GPIO_3 - I2S6_SDO */ + + /* NFC Reset */ + PAD_CFG_GPO(GPIO_150, 1, DEEP) /* ISH_GPIO_4 */ + + PAD_CFG_GPI(GPIO_151, UP_20K, DEEP) /* ISH_GPIO_5 - unused */ + + /* Touch enable */ + PAD_CFG_GPO(GPIO_152, 1, DEEP) /* ISH_GPIO_6 */ + + PAD_CFG_GPI(GPIO_153, UP_20K, DEEP) /* ISH_GPIO_7 - unused */ + PAD_CFG_GPI(GPIO_154, UP_20K, DEEP) /* ISH_GPIO_8 - unused */ + PAD_CFG_GPI(GPIO_155, UP_20K, DEEP) /* ISH_GPIO_9 - unused */ + + /* PCIE_CLKREQ[0:3]_N */ + PAD_CFG_NF(GPIO_209, NONE, DEEP, NF1) /* WLAN with external pull */ + PAD_CFG_GPI(GPIO_210, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_211, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_212, UP_20K, DEEP) /* unused */ + + /* OSC_CLK_OUT_[0:4] -- unused */ + PAD_CFG_GPI(OSC_CLK_OUT_0, UP_20K, DEEP) + PAD_CFG_GPI(OSC_CLK_OUT_1, UP_20K, DEEP) + PAD_CFG_GPI(OSC_CLK_OUT_2, UP_20K, DEEP) + PAD_CFG_GPI(OSC_CLK_OUT_3, UP_20K, DEEP) + PAD_CFG_GPI(OSC_CLK_OUT_4, UP_20K, DEEP) + + /* PMU Signals */ + PAD_CFG_GPI(PMU_AC_PRESENT, UP_20K, DEEP) /* PMU_AC_PRESENT - unused */ + PAD_CFG_NF(PMU_BATLOW_B, UP_20K, DEEP, NF1) /* PMU_BATLOW_N */ + PAD_CFG_NF(PMU_PLTRST_B, NONE, DEEP, NF1) /* PMU_PLTRST_N */ + PAD_CFG_NF(PMU_PWRBTN_B, UP_20K, DEEP, NF1) /* PMU_PWRBTN_N */ + PAD_CFG_NF(PMU_RESETBUTTON_B, NONE, DEEP, NF1) /* PMU_RSTBTN_N */ + PAD_CFG_NF_IOSSTATE(PMU_SLP_S0_B, NONE, DEEP, NF1, IGNORE) /* PMU_SLP_S0_N */ + PAD_CFG_NF(PMU_SLP_S3_B, NONE, DEEP, NF1) /* PMU_SLP_S3_N */ + PAD_CFG_NF(PMU_SLP_S4_B, NONE, DEEP, NF1) /* PMU_SLP_S4_N */ + PAD_CFG_NF(PMU_SUSCLK, NONE, DEEP, NF1) /* PMU_SUSCLK */ + PAD_CFG_GPO(PMU_WAKE_B, 1, DEEP) /* EN_PP3300_EMMC */ + PAD_CFG_NF(SUS_STAT_B, NONE, DEEP, NF1) /* SUS_STAT_N */ + PAD_CFG_NF(SUSPWRDNACK, NONE, DEEP, NF1) /* SUSPWRDNACK */ + + /* DDI[0:1] SDA and SCL -- unused */ + PAD_CFG_GPI(GPIO_187, UP_20K, DEEP) /* HV_DDI0_DDC_SDA */ + PAD_CFG_GPI(GPIO_188, UP_20K, DEEP) /* HV_DDI0_DDC_SCL */ + PAD_CFG_GPI(GPIO_189, UP_20K, DEEP) /* HV_DDI1_DDC_SDA */ + PAD_CFG_GPI(GPIO_190, UP_20K, DEEP) /* HV_DDI1_DDC_SCL */ + + /* MIPI I2C -- unused */ + PAD_CFG_GPI(GPIO_191, UP_20K, DEEP) /* MIPI_I2C_SDA */ + PAD_CFG_GPI(GPIO_192, UP_20K, DEEP) /* MIPI_I2C_SCL */ + + /* Panel 0 control */ + PAD_CFG_NF(GPIO_193, NATIVE, DEEP, NF1) /* PNL0_VDDEN */ + PAD_CFG_NF(GPIO_194, NATIVE, DEEP, NF1) /* PNL0_BKLTEN */ + PAD_CFG_NF(GPIO_195, NATIVE, DEEP, NF1) /* PNL0_BKLTCTL */ + + /* Panel 1 control -- unused */ + PAD_CFG_NF(GPIO_196, NATIVE, DEEP, NF1) /* PNL1_VDDEN */ + PAD_CFG_NF(GPIO_197, NATIVE, DEEP, NF1) /* PNL1_BKLTEN */ + PAD_CFG_NF(GPIO_198, NATIVE, DEEP, NF1) /* PNL1_BKLTCTL */ + + /* Hot plug detect */ + PAD_CFG_NF(GPIO_199, UP_20K, DEEP, NF2) /* HV_DDI1_HPD */ + PAD_CFG_NF(GPIO_200, UP_20K, DEEP, NF2) /* HV_DDI0_HPD */ + + /* MDSI signals -- unused */ + PAD_CFG_GPI(GPIO_201, UP_20K, DEEP) /* MDSI_A_TE */ + PAD_CFG_GPI(GPIO_202, UP_20K, DEEP) /* MDSI_A_TE */ + + /* USB overcurrent pins */ + PAD_CFG_NF(GPIO_203, UP_20K, DEEP, NF1) /* USB_OC0_N */ + PAD_CFG_NF(GPIO_204, UP_20K, DEEP, NF1) /* USB_OC1_N */ + + /* PMC SPI -- almost entirely unused */ + PAD_CFG_GPI(PMC_SPI_FS0, UP_20K, DEEP) + PAD_CFG_NF(PMC_SPI_FS1, UP_20K, DEEP, NF2) /* HV_DDI2_HPD -- EDP HPD */ + PAD_CFG_GPI(PMC_SPI_FS2, UP_20K, DEEP) + PAD_CFG_GPI(PMC_SPI_RXD, UP_20K, DEEP) + PAD_CFG_GPI(PMC_SPI_TXD, UP_20K, DEEP) + PAD_CFG_GPI(PMC_SPI_CLK, UP_20K, DEEP) + + /* PMIC Signals Unused signals related to an old PMIC interface */ + PAD_CFG_NF_IOSSTATE(PMIC_RESET_B, NATIVE, DEEP, NF1, IGNORE) /* PMIC_RESET_B */ + PAD_CFG_GPI(GPIO_213, NONE, DEEP) /* unused external pull */ + PAD_CFG_GPI(GPIO_214, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_215, UP_20K, DEEP) /* unused */ + PAD_CFG_NF(PMIC_THERMTRIP_B, UP_20K, DEEP, NF1) /* THERMTRIP_N */ + PAD_CFG_GPI(PMIC_STDBY, UP_20K, DEEP) /* unused */ + PAD_CFG_NF(PROCHOT_B, UP_20K, DEEP, NF1) /* PROCHOT_N */ + PAD_CFG_NF(PMIC_I2C_SCL, UP_1K, DEEP, NF1) /* PMIC_I2C_SCL */ + PAD_CFG_NF(PMIC_I2C_SDA, UP_1K, DEEP, NF1) /* PMIC_I2C_SDA */ + + /* I2S1 -- largely unused */ + PAD_CFG_GPI(GPIO_74, UP_20K, DEEP) /* I2S1_MCLK */ + PAD_CFG_GPI(GPIO_75, UP_20K, DEEP) /* I2S1_BCLK -- PCH_WP */ + PAD_CFG_GPO(GPIO_76, 0, DEEP) /* I2S1_WS_SYNC -- SPK_PA_EN */ + PAD_CFG_GPI(GPIO_77, UP_20K, DEEP) /* I2S1_SDI */ + PAD_CFG_GPO(GPIO_78, 1, DEEP) /* I2S1_SDO -- EN_PP3300_DX_LTE_SOC */ + + /* DMIC or I2S4 */ + /* AVS_DMIC_CLK_A1 */ + PAD_CFG_NF_IOSSTATE(GPIO_79, NATIVE, DEEP, NF1, IGNORE) + PAD_CFG_NF(GPIO_80, NATIVE, DEEP, NF1) /* AVS_DMIC_CLK_B1 */ + PAD_CFG_NF(GPIO_81, NATIVE, DEEP, NF1) /* AVS_DMIC_DATA_1 */ + PAD_CFG_GPI(GPIO_82, DN_20K, DEEP) /* unused -- strap */ + PAD_CFG_NF(GPIO_83, NATIVE, DEEP, NF1) /* AVS_DMIC_DATA_2 */ + + /* I2S2 -- Headset amp */ + PAD_CFG_NF(GPIO_84, NATIVE, DEEP, NF1) /* AVS_I2S2_MCLK */ + PAD_CFG_NF(GPIO_85, NATIVE, DEEP, NF1) /* AVS_I2S2_BCLK */ + PAD_CFG_NF(GPIO_86, NATIVE, DEEP, NF1) /* AVS_I2S2_SW_SYNC */ + PAD_CFG_NF(GPIO_87, NATIVE, DEEP, NF1) /* AVS_I2S2_SDI */ + PAD_CFG_NF(GPIO_88, NATIVE, DEEP, NF1) /* AVS_I2S2_SDO */ + + /* I2S3 -- largely unused */ + PAD_CFG_GPI(GPIO_89, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_90, UP_20K, DEEP) /* GPS_HOST_WAKE */ + PAD_CFG_GPO(GPIO_91, 1, DEEP) /* GPS_EN */ + PAD_CFG_GPI(GPIO_92, DN_20K, DEEP) /* unused -- strap */ + + /* Fast SPI */ + PAD_CFG_NF_IOSSTATE(GPIO_97, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CS0_B */ + PAD_CFG_GPI(GPIO_98, UP_20K, DEEP) /* FST_SPI_CS1_B -- unused */ + PAD_CFG_NF_IOSSTATE(GPIO_99, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_MOSI_IO0 */ + PAD_CFG_NF_IOSSTATE(GPIO_100, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_MISO_IO1 */ + PAD_CFG_GPI(GPIO_101, NONE, DEEP) /* FST_IO2 -- MEM_CONFIG0 */ + PAD_CFG_GPI(GPIO_102, NONE, DEEP) /* FST_IO3 -- MEM_CONFIG1 */ + PAD_CFG_NF_IOSSTATE(GPIO_103, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CLK */ + PAD_CFG_NF_IOSSTATE(FST_SPI_CLK_FB, NATIVE, DEEP, NF1, IGNORE) /* FST_SPI_CLK_FB */ + PAD_CFG_NF_IOSSTATE(GPIO_106, NATIVE, DEEP, NF3, IGNORE) /* FST_SPI_CS2_N */ + + /* SIO_SPI_0 - Used for FP */ + PAD_CFG_NF(GPIO_104, NATIVE, DEEP, NF1) /* SIO_SPI_0_CLK */ + PAD_CFG_NF(GPIO_105, NATIVE, DEEP, NF1) /* SIO_SPI_0_FS0 */ + PAD_CFG_NF(GPIO_109, NATIVE, DEEP, NF1) /* SIO_SPI_0_RXD */ + PAD_CFG_NF(GPIO_110, NATIVE, DEEP, NF1) /* SIO_SPI_0_TXD */ + + /* SIO_SPI_1 -- largely unused */ + PAD_CFG_GPI(GPIO_111, UP_20K, DEEP) /* SIO_SPI_1_CLK */ + PAD_CFG_GPI(GPIO_112, UP_20K, DEEP) /* SIO_SPI_1_FS0 */ + PAD_CFG_GPI(GPIO_113, UP_20K, DEEP) /* SIO_SPI_1_FS1 */ + /* Headset interrupt */ + PAD_CFG_GPI_APIC_LOW(GPIO_116, NONE, DEEP) /* SIO_SPI_1_RXD */ + PAD_CFG_GPI(GPIO_117, UP_20K, DEEP) /* SIO_SPI_1_TXD */ + + /* SIO_SPI_2 -- unused */ + PAD_CFG_GPI(GPIO_118, UP_20K, DEEP) /* SIO_SPI_2_CLK */ + PAD_CFG_GPI(GPIO_119, UP_20K, DEEP) /* SIO_SPI_2_FS0 */ + PAD_CFG_GPI(GPIO_120, UP_20K, DEEP) /* SIO_SPI_2_FS1 */ + PAD_CFG_GPI(GPIO_121, UP_20K, DEEP) /* SIO_SPI_2_FS2 */ + /* WLAN_PE_RST - default to deasserted */ + PAD_CFG_GPO(GPIO_122, 0, DEEP) /* SIO_SPI_2_RXD */ + PAD_CFG_GPI(GPIO_123, UP_20K, DEEP) /* SIO_SPI_2_TXD */ + + /* Debug tracing */ + PAD_CFG_GPI(GPIO_0, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_1, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_2, UP_20K, DEEP) + PAD_CFG_GPI_SCI_HIGH(GPIO_3, DN_20K, DEEP, LEVEL) /* FP_INT */ + PAD_CFG_GPI(GPIO_4, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_5, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_6, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_7, UP_20K, DEEP) + PAD_CFG_GPI(GPIO_8, UP_20K, DEEP) + + PAD_CFG_GPI_APIC_LOW(GPIO_9, NONE, DEEP) /* dTPM IRQ */ + PAD_CFG_GPI(GPIO_10, DN_20K, DEEP) /* Board phase enforcement */ + PAD_CFG_GPI_SCI_LOW(GPIO_11, NONE, DEEP, EDGE_SINGLE) /* EC SCI */ + PAD_CFG_GPI(GPIO_12, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI_APIC_LOW(GPIO_13, NONE, DEEP) /* PEN_INT_ODL */ + PAD_CFG_GPI_APIC_HIGH(GPIO_14, DN_20K, DEEP) /* FP_INT */ + PAD_CFG_GPI_SCI_LOW(GPIO_15, NONE, DEEP, EDGE_SINGLE) /* TRACKPAD_INT_1V8_ODL */ + PAD_CFG_GPI(GPIO_16, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_17, UP_20K, DEEP) /* 1 vs 4 DMIC config */ + PAD_CFG_GPI_APIC_LOW(GPIO_18, NONE, DEEP) /* Trackpad IRQ */ + PAD_CFG_GPI(GPIO_19, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI_APIC_LOW(GPIO_20, UP_20K, DEEP) /* NFC IRQ */ + PAD_CFG_GPI_APIC_LOW(GPIO_21, NONE, DEEP) /* Touch IRQ */ + PAD_CFG_GPI_SCI_LOW(GPIO_22, NONE, DEEP, EDGE_SINGLE) /* EC wake */ + PAD_CFG_GPI(GPIO_23, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_24, NONE, DEEP) /* PEN_PDCT_ODL */ + PAD_CFG_GPI(GPIO_25, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_26, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI(GPIO_27, UP_20K, DEEP) /* unused */ + PAD_CFG_GPI_APIC_LOW(GPIO_28, NONE, DEEP) /* TPM IRQ */ + PAD_CFG_GPO(GPIO_29, 1, DEEP) /* FP reset */ + PAD_CFG_GPI_APIC_LOW(GPIO_30, NONE, DEEP) /* KB IRQ */ + PAD_CFG_GPO(GPIO_31, 0, DEEP) /* NFC FW DL */ + PAD_CFG_NF(GPIO_32, NONE, DEEP, NF5) /* SUS_CLK2 */ + PAD_CFG_GPI_APIC_LOW(GPIO_33, NONE, DEEP) /* PMIC IRQ */ + PAD_CFG_GPI(GPIO_34, UP_20K, DEEP) /* unused */ + PAD_CFG_GPO(GPIO_35, 0, DEEP) /* PEN_RESET - active high */ + PAD_CFG_GPO(GPIO_36, 0, DEEP) /* touch reset */ + PAD_CFG_GPI(GPIO_37, UP_20K, DEEP) /* unused */ + + /* LPSS_UART[0:2] */ + PAD_CFG_GPI(GPIO_38, NONE, DEEP) /* LPSS_UART0_RXD - MEM_CONFIG2*/ + /* Next 2 are straps */ + PAD_CFG_GPI(GPIO_39, DN_20K, DEEP) /* LPSS_UART0_TXD - unused */ + PAD_CFG_GPI(GPIO_40, DN_20K, DEEP) /* LPSS_UART0_RTS - unused */ + PAD_CFG_GPI(GPIO_41, NONE, DEEP) /* LPSS_UART0_CTS - EC_IN_RW */ + PAD_CFG_NF(GPIO_42, NATIVE, DEEP, NF1) /* LPSS_UART1_RXD */ + PAD_CFG_NF(GPIO_43, NATIVE, DEEP, NF1) /* LPSS_UART1_TXD */ + PAD_CFG_GPO(GPIO_44, 1, DEEP) /* GPS_RST_ODL */ + PAD_CFG_GPI(GPIO_45, NONE, DEEP) /* LPSS_UART1_CTS - MEM_CONFIG3 */ + PAD_CFG_NF(GPIO_46, NATIVE, DEEP, NF1) /* LPSS_UART2_RXD */ + PAD_CFG_NF_IOSSTATE(GPIO_47, NATIVE, DEEP, NF1, TX1_RX_DCR_X0) /* UART2 TX */ + PAD_CFG_GPI(GPIO_48, UP_20K, DEEP) /* LPSS_UART2_RTS - unused */ + PAD_CFG_GPI_SMI_LOW(GPIO_49, NONE, DEEP, EDGE_SINGLE) /* LPSS_UART2_CTS - EC_SMI_L */ + + /* Camera interface -- completely unused */ + PAD_CFG_GPI(GPIO_62, UP_20K, DEEP) /* GP_CAMERASB00 */ + PAD_CFG_GPI(GPIO_63, UP_20K, DEEP) /* GP_CAMERASB01 */ + PAD_CFG_GPI(GPIO_64, UP_20K, DEEP) /* GP_CAMERASB02 */ + PAD_CFG_GPI(GPIO_65, UP_20K, DEEP) /* GP_CAMERASB03 */ + PAD_CFG_GPI(GPIO_66, UP_20K, DEEP) /* GP_CAMERASB04 */ + PAD_CFG_GPI(GPIO_67, UP_20K, DEEP) /* GP_CAMERASB05 */ + PAD_CFG_GPI(GPIO_68, UP_20K, DEEP) /* GP_CAMERASB06 */ + PAD_CFG_GPI(GPIO_69, UP_20K, DEEP) /* GP_CAMERASB07 */ + PAD_CFG_GPI(GPIO_70, UP_20K, DEEP) /* GP_CAMERASB08 */ + PAD_CFG_GPI(GPIO_71, UP_20K, DEEP) /* GP_CAMERASB09 */ + PAD_CFG_GPI(GPIO_72, UP_20K, DEEP) /* GP_CAMERASB10 */ + PAD_CFG_GPI(GPIO_73, UP_20K, DEEP) /* GP_CAMERASB11 */ + >; +}; diff --git a/board/google/Kconfig b/board/google/Kconfig index 679a0f1023..22c4be392f 100644 --- a/board/google/Kconfig +++ b/board/google/Kconfig @@ -8,6 +8,20 @@ choice prompt "Mainboard model" optional
+config TARGET_CHROMEBOOK_CORAL + bool "Chromebook coral" + help + This is a range of Intel-based laptops released in 2018. They use an + Intel Apollo Lake SoC. 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). + config TARGET_CHROMEBOOK_LINK bool "Chromebook link" help @@ -62,6 +76,7 @@ config TARGET_CHROMEBOOK_SAMUS_TPL
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 0000000000..940bee89b0 --- /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 0000000000..904227e2e2 --- /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 0000000000..6a27ce3da1 --- /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 0000000000..4e34710b97 --- /dev/null +++ b/board/google/chromebook_coral/coral.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> + +int arch_misc_init(void) +{ + return 0; +} + +/* This function is needed if CONFIG_CMDLINE is not enabled */ +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 0000000000..566d47d22f --- /dev/null +++ b/configs/chromebook_coral_defconfig @@ -0,0 +1,102 @@ +CONFIG_X86=y +CONFIG_SYS_TEXT_BASE=0x1110000 +CONFIG_SYS_MALLOC_F_LEN=0x3d00 +CONFIG_SPL_SYS_MALLOC_F_LEN=0xf000 +CONFIG_NR_DRAM_BANKS=8 +CONFIG_BOOTSTAGE_STASH_ADDR=0xfef00000 +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_SPL_BOOTSTAGE=y +CONFIG_TPL_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10 +CONFIG_BOOTSTAGE_STASH=y +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro earlyprintk console=tty0 console=ttyS0,115200" +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_PCI=y +# CONFIG_SPL_SPI_FLASH_TINY 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_READ=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_WINBOND=y +# CONFIG_X86_PCH7 is not set +# CONFIG_X86_PCH9 is not set +CONFIG_PINCTRL=y +# CONFIG_SPL_PINCTRL_FULL 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_ICH_SPI=y +CONFIG_TPL_SYSRESET=y +CONFIG_TPM_TIS_LPC=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_KEYBOARD=y +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 0000000000..515fd06d76 --- /dev/null +++ b/doc/board/google/chromebook_coral.rst @@ -0,0 +1,241 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Simon Glass sjg@chromium.org + +Chromebook Coral +================ + +Coral is a Chromebook (or really about 20 different Chromebooks) which use the +Intel Apollo Lake platform (APL). The 'reef' Chromebooks use the same APL SoC so +should also work. Some later ones based on Glacier Lake (GLK) need various +changes in GPIOs, etc. but are very similar. + +It is hoped that this port can enable ports to embedded APL boards which are +starting to appear. + +Note that booting U-Boot on APL is already supported by coreboot and +Slim Bootloader. This documentation refers to a 'bare metal' port. + + +Boot flow - TPL +--------------- + +Apollo Lake boots via an IFWI (Integrated Firmware Image). TPL is placed in +this, in the IBBL entry. + +On boot, an on-chip microcontroller called the CSE (Converged Security Engine) +sets up some SDRAM at ffff8000 and loads the TPL image to that address. The +SRAM extends up to the top of 32-bit address space, but the last 2KB is the +start16 region, so the TPL image must be 30KB at most, and CONFIG_TPL_TEXT_BASE +must be ffff8000. Actually the start16 region is small and it could probably +move from f800 to fe00, providing another 1.5KB, but TPL is only about 19KB so +there is no need to change it at present. The size limit is enforced by +CONFIG_TPL_SIZE_LIMIT to avoid producing images that won't boot. + +TPL (running from start.S) first sets up CAR (Cache-as-RAM) which provides +larger area of RAM for use while booting. CAR is mapped at CONFIG_SYS_CAR_ADDR +(fef00000) and is 768KB in size. It then sets up the stack in the botttom 64KB +of this space (i.e. below fef10000). This means that the stack and early +malloc() region in TPL can be 64KB at most. + +TPL operates without CONFIG_TPL_PCI enabled so PCI config access must use the +x86-specific functions pci_x86_write_config(), etc. SPL creates a simple-bus +device so that PCI devices are bound by driver model. Then arch_cpu_init_tpl() +is called to early init on various devices. This includes placing PCI devices +at hard-coded addresses in the memory map. PCI auto-config is not used. + +Most of the 16KB ROM is mapped into the very top of memory, except for the +Intel descriptor (first 4KB) and the space for SRAM as above. + +TPL does not set up a bloblist since at present it does not have anything to +pass to SPL. + +Once TPL is done it loads SPL from ROM using either the memory-mapped SPI or by +using the Intel fast SPI driver. SPL is loaded into CAR, at the address given +by CONFIG_SPL_TEXT_BASE, which is normally fef10000. + +Note that booting using the SPI driver results in an TPL image that is about +26KB in size instead of 19KB. Also boot speed is worse by about 340ms. If you +really want to use the driver, enable CONFIG_APL_SPI_FLASH_BOOT and set +BOOT_FROM_FAST_SPI_FLASH to true[2]. + + +Boot flow - SPL +--------------- + +SPL (running from start_from_tpl.S) continues to use the same stack as TPL. +It calls arch_cpu_init_spl() to set up a few devices, then init_dram() loads +the FSP-M binary into CAR and runs to, to set up SDRAM. The address of the +output 'HOB' list (Hand-off-block) is stored into gd->arch.hob_list for parsing. +There is a 2GB chunk of SDRAM starting at 0 and the rest is at 4GB. + +PCI auto-config is not used in SPL either, but CONFIG_SPL_PCI is defined, so +proper PCI access is available and normal dm_pci_read_config() calls can be +used. However PCI auto-config is not used so the same static memory mapping set +up by TPL is still active. + +SPL on x86 always runs with CONFIG_SPL_SEPARATE_BSS=y and BSS is at 120000 +(see u-boot-spl.lds). This works because SPL doesn't access BSS until after +board_init_r(), as per the rules, and DRAM is available then. + +SPL sets up a bloblist and passes the SPL hand-off information to U-Boot proper. +This includes a pointer to the HOB list as well as DRAM information. See +struct arch_spl_handoff. The bloblist address is set by CONFIG_BLOBLIST_ADDR, +normally 100000. + +SPL uses SPI flash to update the MRC caches in ROM. This speeds up subsequent +boots. Be warned that SPL can take 30 seconds without this cache! This is a +known issue with Intel SoCs with modern DRAM and apparently cannot be improved. +The MRC caches are used to work around this. + +Once SPL is finished it loads U-Boot into SDRAM at CONFIG_SYS_TEXT_BASE, which +is normally 1110000. Note that CAR is still active. + + +Boot flow - U-Boot pre-relocation +--------------------------------- + +U-Boot (running from start_from_spl.S) starts running in RAM and uses the same +stack as SPL. It does various init activities before relocation. Notably +arch_cpu_init_dm() sets up the pin muxing for the chip using a very large table +in the device tree. + +PCI auto-config is not used before relocation, but CONFIG_PCI of course is +defined, so proper PCI access is available. The same static memory mapping set +up by TPL is still active until relocation. + +As per usual, U-Boot allocates memory at the top of available RAM (a bit below +2GB in this case) and copies things there ready to relocate itself. Notably +reserve_arch() does not reserve space for the HOB list returned by FSP-M since +this is already located in RAM. + +U-Boot then shuts down CAR and jumps to its relocated version. + + +Boot flow - U-Boot post-relocation +--------------------------------- + +U-Boot starts up normally, running near the top of RAM. After driver model is +running, arch_fsp_init_r() is called which loads and runs the FSP-S binary. +This updates the HOB list to include graphics information, used by the fsp_video +driver. + +PCI autoconfig is done and a few devices are probed to complete init. Most +others are started only when they are used. + +Note that FSP-S is supposed to run after CAR has been shut down, which happens +immediately before U-Boot starts up in its relocated position. Therefore we +cannot run FSP-S before relocation. On the other hand we must run it before +PCI auto-config is done, since FSP-S may show or hide devices. The first device +that probes PCI after relocation is the serial port, in initr_serial(), so FSP-S +must run before that. A corollary is that loading FSP-S must be done without +using the SPI driver, to avoid probing PCI and causing an autoconfig, so +memory-mapped reading is always used for FSP-S. + +It would be possible to tear down CAR in SPL instead of U-Boot. The SPL handoff +information could make sure it does not include any pointers into CAR (in fact +it doesn't). But tearing down CAR in U-Boot allows the initial state used by TPL +and SPL to be read by U-Boot, which seems useful. It also matches how older +platforms start up (those that don't use SPL). + + +Performance +----------- + +Bootstage is used through all phases of U-Boot to keep accurate timimgs for +boot. Use 'bootstage report' in U-Boot to see the report, e.g.: + +Timer summary in microseconds (16 records): + Mark Elapsed Stage + 0 0 reset + 155,325 155,325 TPL + 204,014 48,689 end TPL + 204,385 371 SPL + 738,633 534,248 end SPL + 739,161 528 board_init_f + 842,764 103,603 board_init_r + 1,166,233 323,469 main_loop + 1,166,283 50 id=175 + +Accumulated time: + 62 fast_spi + 202 dm_r + 7,779 dm_spl + 15,555 dm_f + 208,357 fsp-m + 239,847 fsp-s + 292,143 mmap_spi + +CPU performance is about 3500 DMIPS: + +=> dhry +1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS + + +Partial memory map +------------------ + +ffffffff Top of ROM (and last byte of 32-bit address space) +ffff8000 TPL loaded here (from IFWI) +ff000000 Bottom of ROM +fefc000 Top of CAR region +fef96000 Stack for FSP-M +fef40000 59000 FSP-M +fef11000 SPL loaded here +fef10000 CONFIG_BLOBLIST_ADDR +fef10000 Stack top in TPL, SPL and U-Boot before relocation +fef00000 1000 CONFIG_BOOTSTAGE_STASH_ADDR +fef00000 Base of CAR region + + f0000 CONFIG_ROM_TABLE_ADDR + 120000 BSS (defined in u-boot-spl.lds) + 200000 FSP-S (which is run after U-Boot is relocated) + 1110000 CONFIG_SYS_TEXT_BASE + + +Supported peripherals +--------------------- + +- UART +- SPI flash +- Video +- MMC (dev 0) and micro-SD (dev 1) +- Chrome OS EC +- Keyboard +- USB + + +To do +----- + +- Finish peripherals + - left-side USB + - USB-C + - Cr50 (security chip: a basic driver is running but not included here) + - I2C (driver exists but not enabled in device tree) + - Sound (Intel I2S support exists, but need da7219 driver) + - RTC (driver exists but not enabled in device tree) + - Various minor features supported by LPC, etc. +- Booting Chrome OS, e.g. with verified boot +- Integrate with Chrome OS vboot +- Improvements to booting from coreboot (i.e. as a coreboot target) +- Use FSP-T binary instead of our own CAR implementation +- Use the official FSP package instead of the coreboot one +- Enable all CPU cores +- Suspend / resume +- ACPI + + +Credits +------- + +This is a spare-time project conducted slowly over a long period of time. + +Much of the code for this port came from Coreboot, an open-source firmware +project similar to U-Boot's SPL in terms of features. + +Also see [2] for information about the boot flow used by coreboot. It is +similar, but has an extra postcar stage. U-Boot doesn't need this since it +supports relocating itself in memory. + + +[2] Intel PDF https://www.coreboot.org/images/2/23/Apollolake_SoC.pdf diff --git a/doc/board/google/index.rst b/doc/board/google/index.rst index 7f557feb44..061c797718 100644 --- a/doc/board/google/index.rst +++ b/doc/board/google/index.rst @@ -6,5 +6,6 @@ Google .. toctree:: :maxdepth: 2
+ chromebook_coral chromebook_link chromebook_samus diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h new file mode 100644 index 0000000000..a63c3c9eea --- /dev/null +++ b/include/configs/chromebook_coral.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 Google LLC + */ + +/* + * board/config.h - configuration options, board-specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_BOOTCOMMAND \ + "fatload mmc 1:c 1000000 syslinux/vmlinuz.A; zboot 1000000" + +#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 */

On Mon, Dec 9, 2019 at 8:42 AM Simon Glass sjg@chromium.org wrote:
Add support for coral which is a range of Apollo Lake-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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7:
- Add the new documentation to the index file
Changes in v6:
- Add a comment about the need for board_run_command()
- Use generic gpio compatible string
Changes in v5:
- Add gpio-controller to GPIO nodes
- Comment out GPIOs in the fsp_s node since we don't use them yet
- Correct CPU ACPI IDs
- Use a define for ACPI base address
Changes in v4:
- Add u-boot,skip-auto-config-until-reloc property to PCI
- Drop duplicate commit 'Create a new sandbox_pci_read_bar() function'
- New GPIO driver binding
- Set up LPC pads early
- Switch over to use pinctrl for pad init/config
- Update documentation with more detailed memory map
- Use hyphen for device-tree properties
- apollolake -> Apollo Lake
Changes in v3:
- Ad FSP-S support
- Add CONFIG_TPL_X86_ASSUME_CPUID to reduce code size
- Add Chrome OS EC support
- Add a proper SPI node and make the SPI flash node a child
- Add bootstage support
- Add more documentation
- Add spi alias in device tree
- Disable the bootcommand since it does nothing useful on coral
- Don't enable SPI flash in TPL by default
- Drop CONFIG_SPL_NET_SUPPORT
- Drop patch '86: timer: Reduce timer code size in TPL on Intel CPUs'
- Drop patch 'dm: core: Don't include ofnode functions with of-platdata'
- Drop patch 'spi: sandbox: Add a test driver for sandbox SPI flash'
- Drop patch 'spl: Allow SPL/TPL to use of-platdata without libfdt'
- Drop patch 'x86: apollolake: Add definitions for the Intel Fast SPI interface'
- Drop patch 'x86: timer: Set up the timer in timer_early_get_count()'
- Enable video and USB3
- Reduce amount of early-pad data in TPL
- Tidy up the pad settings in the device tree
- Use a zero-based tsc timer
Changes in v2: None
arch/x86/dts/Makefile | 1 + arch/x86/dts/chromebook_coral.dts | 831 ++++++++++++++++++++++ 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 | 19 + configs/chromebook_coral_defconfig | 102 +++ doc/board/google/chromebook_coral.rst | 241 +++++++ doc/board/google/index.rst | 1 + include/configs/chromebook_coral.h | 32 + 11 files changed, 1296 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
applied to u-boot-x86/next, thanks!

On Mon, Dec 9, 2019 at 8:40 AM Simon Glass sjg@chromium.org wrote:
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v7: None Changes in v6:
- Fix comments for struct apl_hostbridge_platdata
Changes in v5: None Changes in v4:
- Avoid needing to know internals of pinctrl in this driver
- Move code to pinctrl driver
- Switch over to use pinctrl for pad init/config
Changes in v3:
- Move pad programming into the hostbridge to reduce TPL device-tree size
- Use pci_get_devfn()
Changes in v2: None
arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/hostbridge.c | 179 +++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 arch/x86/cpu/apollolake/hostbridge.c
applied to u-boot-x86/next, thanks!
participants (2)
-
Bin Meng
-
Simon Glass