
On 15 August 2017 at 23:41, Bin Meng bmeng.cn@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@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@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@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@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@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@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@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