[U-Boot] [PATCH 09/13] x86: Add Intel Braswell SoC support
Simon Glass
sjg at chromium.org
Sat Aug 26 13:39:10 UTC 2017
On 15 August 2017 at 23:41, Bin Meng <bmeng.cn at gmail.com> wrote:
> This adds initial Intel Braswell SoC support. It uses Intel FSP
> to initialize the chipset.
>
> Similar to its predecessor BayTrail, there are some work to do to
> enable the legacy UART integrated in the Braswell SoC.
>
> Signed-off-by: Bin Meng <bmeng.cn at gmail.com>
> ---
>
> arch/x86/Kconfig | 1 +
> arch/x86/cpu/Makefile | 1 +
> arch/x86/cpu/braswell/Kconfig | 38 +++++++
> arch/x86/cpu/braswell/Makefile | 7 ++
> arch/x86/cpu/braswell/braswell.c | 36 ++++++
> arch/x86/cpu/braswell/cpu.c | 170 +++++++++++++++++++++++++++++
> arch/x86/cpu/braswell/early_uart.c | 86 +++++++++++++++
> arch/x86/include/asm/arch-braswell/iomap.h | 50 +++++++++
> 8 files changed, 389 insertions(+)
> create mode 100644 arch/x86/cpu/braswell/Kconfig
> create mode 100644 arch/x86/cpu/braswell/Makefile
> create mode 100644 arch/x86/cpu/braswell/braswell.c
> create mode 100644 arch/x86/cpu/braswell/cpu.c
> create mode 100644 arch/x86/cpu/braswell/early_uart.c
> create mode 100644 arch/x86/include/asm/arch-braswell/iomap.h
Reviewed-by: Simon Glass <sjg at chromium.org>
A few nits / suggestions below.
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index f72d307..9620764 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -108,6 +108,7 @@ source "board/intel/Kconfig"
>
> # platform-specific options below
> source "arch/x86/cpu/baytrail/Kconfig"
> +source "arch/x86/cpu/braswell/Kconfig"
> source "arch/x86/cpu/broadwell/Kconfig"
> source "arch/x86/cpu/coreboot/Kconfig"
> source "arch/x86/cpu/ivybridge/Kconfig"
> diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
> index 999429e..94cdff1 100644
> --- a/arch/x86/cpu/Makefile
> +++ b/arch/x86/cpu/Makefile
> @@ -27,6 +27,7 @@ endif
>
> obj-y += intel_common/
> obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
> +obj-$(CONFIG_INTEL_BRASWELL) += braswell/
> obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
> obj-$(CONFIG_SYS_COREBOOT) += coreboot/
> obj-$(CONFIG_EFI_APP) += efi/
> diff --git a/arch/x86/cpu/braswell/Kconfig b/arch/x86/cpu/braswell/Kconfig
> new file mode 100644
> index 0000000..c993889
> --- /dev/null
> +++ b/arch/x86/cpu/braswell/Kconfig
> @@ -0,0 +1,38 @@
> +#
> +# Copyright (C) 2017, Bin Meng <bmeng.cn at gmail.com>
> +#
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +
> +config INTEL_BRASWELL
> + bool
> + select HAVE_FSP
> + select ARCH_MISC_INIT
> + imply HAVE_INTEL_ME
> + imply HAVE_VBT
> + imply ENABLE_MRC_CACHE
> + imply ENV_IS_IN_SPI_FLASH
> + imply AHCI_PCI
> + imply ICH_SPI
> + imply MMC
> + imply MMC_PCI
> + imply MMC_SDHCI
> + imply MMC_SDHCI_SDMA
> + imply SCSI
> + imply SPI_FLASH
> + imply SYS_NS16550
> + imply USB
> + imply USB_XHCI_HCD
> + imply VIDEO_FSP
> +
> +if INTEL_BRASWELL
> +
> +config FSP_ADDR
> + hex
> + default 0xfff20000
> +
> +config FSP_LOCKDOWN_SPI
> + bool
> + default y
> +
> +endif
> diff --git a/arch/x86/cpu/braswell/Makefile b/arch/x86/cpu/braswell/Makefile
> new file mode 100644
> index 0000000..19bcee6
> --- /dev/null
> +++ b/arch/x86/cpu/braswell/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Copyright (C) 2017, Bin Meng <bmeng.cn at gmail.com>
> +#
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +
> +obj-y += braswell.o cpu.o early_uart.o
> diff --git a/arch/x86/cpu/braswell/braswell.c b/arch/x86/cpu/braswell/braswell.c
> new file mode 100644
> index 0000000..37099aa
> --- /dev/null
> +++ b/arch/x86/cpu/braswell/braswell.c
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (C) 2017, Bin Meng <bmeng.cn at gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/mrccache.h>
> +#include <asm/post.h>
> +
> +int arch_cpu_init(void)
> +{
> + post_code(POST_CPU_INIT);
> +
> + return x86_cpu_init_f();
> +}
> +
> +int arch_misc_init(void)
> +{
> +#ifdef CONFIG_ENABLE_MRC_CACHE
> + /*
> + * We intend not to check any return value here, as even MRC cache
> + * is not saved successfully, it is not a severe error that will
> + * prevent system from continuing to boot.
> + */
> + mrccache_save();
> +#endif
> +
> + return 0;
> +}
> +
> +void reset_cpu(ulong addr)
> +{
> + /* cold reset */
> + x86_full_reset();
> +}
> diff --git a/arch/x86/cpu/braswell/cpu.c b/arch/x86/cpu/braswell/cpu.c
> new file mode 100644
> index 0000000..6ff9036
> --- /dev/null
> +++ b/arch/x86/cpu/braswell/cpu.c
> @@ -0,0 +1,170 @@
> +/*
> + * Copyright (C) 2017, Bin Meng <bmeng.cn at gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + *
> + * Derived from arch/x86/cpu/baytrail/cpu.c
> + */
> +
> +#include <common.h>
> +#include <cpu.h>
> +#include <dm.h>
> +#include <asm/cpu.h>
> +#include <asm/cpu_x86.h>
> +#include <asm/io.h>
> +#include <asm/lapic.h>
> +#include <asm/msr.h>
> +#include <asm/turbo.h>
> +
> +static const unsigned int braswell_bus_freq_table[] = {
> + 83333333,
> + 100000000,
> + 133333333,
> + 116666666,
> + 80000000,
> + 93333333,
> + 90000000,
> + 88900000,
> + 87500000
> +};
> +
> +static unsigned int braswell_bus_freq(void)
> +{
> + msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
> +
> + if ((clk_info.lo & 0xf) < (ARRAY_SIZE(braswell_bus_freq_table)))
> + return braswell_bus_freq_table[clk_info.lo & 0xf];
> +
> + return 0;
> +}
> +
> +static unsigned long braswell_tsc_freq(void)
> +{
> + msr_t platform_info;
> + ulong bclk = braswell_bus_freq();
> +
> + if (!bclk)
> + return 0;
> +
> + platform_info = msr_read(MSR_PLATFORM_INFO);
> +
> + return bclk * ((platform_info.lo >> 8) & 0xff);
> +}
> +
> +static int braswell_get_info(struct udevice *dev, struct cpu_info *info)
> +{
> + info->cpu_freq = braswell_tsc_freq();
> + info->features = (1 << CPU_FEAT_L1_CACHE) | (1 << CPU_FEAT_MMU);
> +
> + return 0;
> +}
> +
> +static int braswell_get_count(struct udevice *dev)
> +{
> + int ecx = 0;
> +
> + /*
> + * Use the algorithm described in Intel 64 and IA-32 Architectures
> + * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
> + * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
> + * of CPUID Extended Topology Leaf.
> + */
> + while (1) {
> + struct cpuid_result leaf_b;
> +
> + leaf_b = cpuid_ext(0xb, ecx);
> +
> + /*
> + * Braswell doesn't have hyperthreading so just determine the
> + * number of cores by from level type (ecx[15:8] == * 2)
> + */
> + if ((leaf_b.ecx & 0xff00) == 0x0200)
> + return leaf_b.ebx & 0xffff;
> +
> + ecx++;
> + }
> +
> + return 0;
> +}
> +
> +static void braswell_set_max_freq(void)
> +{
> + msr_t perf_ctl;
> + msr_t msr;
> +
> + /* Enable speed step */
> + msr = msr_read(MSR_IA32_MISC_ENABLES);
> + msr.lo |= (1 << 16);
> + msr_write(MSR_IA32_MISC_ENABLES, msr);
> +
> + /* Enable Burst Mode */
> + msr = msr_read(MSR_IA32_MISC_ENABLES);
> + msr.hi = 0;
> + msr_write(MSR_IA32_MISC_ENABLES, msr);
> +
> + /*
> + * Set guaranteed ratio [21:16] from IACORE_TURBO_RATIOS to
> + * bits [15:8] of the PERF_CTL
> + */
> + msr = msr_read(MSR_IACORE_TURBO_RATIOS);
> + perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
> +
> + /*
> + * Set guaranteed vid [22:16] from IACORE_TURBO_VIDS to
> + * bits [7:0] of the PERF_CTL
> + */
> + msr = msr_read(MSR_IACORE_TURBO_VIDS);
> + perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
> +
> + perf_ctl.hi = 0;
> + msr_write(MSR_IA32_PERF_CTL, perf_ctl);
> +}
> +
> +static int braswell_probe(struct udevice *dev)
> +{
> + debug("Init Braswell core\n");
> +
> + /*
> + * On Braswell the turbo disable bit is actually scoped at the
> + * building-block level, not package. For non-BSP cores that are
> + * within a building block, enable turbo. The cores within the BSP's
> + * building block will just see it already enabled and move on.
> + */
> + if (lapicid())
> + turbo_enable();
> +
> + /* Dynamic L2 shrink enable and threshold, clear SINGLE_PCTL bit 11 */
> + msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f080f, 0xe0008),
> + msr_clrsetbits_64(MSR_POWER_MISC,
> + ENABLE_ULFM_AUTOCM_MASK | ENABLE_INDP_AUTOCM_MASK, 0);
> +
> + /* Disable C1E */
> + msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
> + msr_setbits_64(MSR_POWER_MISC, 0x44);
> +
> + /* Set this core to max frequency ratio */
> + braswell_set_max_freq();
> +
> + return 0;
> +}
> +
> +static const struct udevice_id braswell_ids[] = {
> + { .compatible = "intel,braswell-cpu" },
> + { }
> +};
> +
> +static const struct cpu_ops braswell_ops = {
> + .get_desc = cpu_x86_get_desc,
> + .get_info = braswell_get_info,
> + .get_count = braswell_get_count,
> + .get_vendor = cpu_x86_get_vendor,
> +};
> +
> +U_BOOT_DRIVER(cpu_x86_braswell_drv) = {
> + .name = "cpu_x86_braswell",
> + .id = UCLASS_CPU,
> + .of_match = braswell_ids,
> + .bind = cpu_x86_bind,
> + .probe = braswell_probe,
> + .ops = &braswell_ops,
> +};
> diff --git a/arch/x86/cpu/braswell/early_uart.c b/arch/x86/cpu/braswell/early_uart.c
> new file mode 100644
> index 0000000..0300e13
> --- /dev/null
> +++ b/arch/x86/cpu/braswell/early_uart.c
> @@ -0,0 +1,86 @@
> +/*
> + * Copyright (C) 2017, Bin Meng <bmeng.cn at gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +
> +#define PCI_DEV_CONFIG(segbus, dev, fn) ( \
> + (((segbus) & 0xfff) << 20) | \
> + (((dev) & 0x1f) << 15) | \
> + (((fn) & 0x07) << 12))
This seems to be shared by baytrail? Do you think it should go in a header file?
> +
> +/* Platform Controller Unit */
> +#define LPC_DEV 0x1f
> +#define LPC_FUNC 0
> +
> +/* Enable UART */
> +#define UART_CONT 0x80
> +
> +/* UART PAD definitions */
> +#define UART_RXD_COMMUITY 1
> +#define UART_TXD_COMMUITY 1
> +#define UART_RXD_FAMILY 4
> +#define UART_TXD_FAMILY 4
> +#define UART_RXD_PAD 2
> +#define UART_TXD_PAD 7
> +#define UART_RXD_FUNC 3
> +#define UART_TXD_FUNC 3
> +
> +/* IO Memory */
> +#define IO_BASE_ADDRESS 0xfed80000
> +
> +static inline uint32_t gpio_pconf0(int community, int family, int pad)
> +{
> + return IO_BASE_ADDRESS + community * 0x8000 + 0x4400 +
> + family * 0x400 + pad * 8;
> +}
> +
> +static void gpio_select_func(int community, int family, int pad, int func)
> +{
> + uint32_t reg;
> + uint32_t pconf0_addr = gpio_pconf0(community, family, pad);
> +
> + reg = readl(pconf0_addr);
> + reg &= ~(0xf << 16);
> + reg |= (func << 16);
> + writel(reg, pconf0_addr);
Can we use setclrbits_le32()?
> +}
> +
> +static void x86_pci_write_config32(int dev, unsigned int where, u32 value)
> +{
> + unsigned long addr;
> +
> + addr = CONFIG_PCIE_ECAM_BASE | dev | (where & ~3);
> + writel(value, addr);
> +}
> +
Regards,
Simon
More information about the U-Boot
mailing list