[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