On 15 August 2017 at 23:41, Bin Meng <bmeng...@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...@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 <s...@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...@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...@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...@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...@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...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot