Commit 605e15db authored by Tom Rini's avatar Tom Rini
parents 4905dfc6 f110da99
......@@ -1035,8 +1035,8 @@ ifneq ($(CONFIG_HAVE_CMC),)
IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE)
endif
ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),)
IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILE)
ifneq ($(CONFIG_HAVE_VGA_BIOS),)
IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE)
endif
quiet_cmd_ifdtool = IFDTOOL $@
......
......@@ -69,6 +69,21 @@ config X86_RESET_VECTOR
bool
default n
config RESET_SEG_START
hex
depends on X86_RESET_VECTOR
default 0xffff0000
config RESET_SEG_SIZE
hex
depends on X86_RESET_VECTOR
default 0x10000
config RESET_VEC_LOC
hex
depends on X86_RESET_VECTOR
default 0xfffffff0
config SYS_X86_START16
hex
depends on X86_RESET_VECTOR
......@@ -173,14 +188,6 @@ config X86_RAMTEST
to work correctly. It is not exhaustive but can save time by
detecting obvious failures.
config MARK_GRAPHICS_MEM_WRCOMB
bool "Mark graphics memory as write-combining"
default n
help
The graphics performance may increase if the graphics
memory is set as write-combining cache type. This option
enables marking the graphics memory as write-combining.
config HAVE_FSP
bool "Add an Firmware Support Package binary"
help
......@@ -220,17 +227,6 @@ config FSP_TEMP_RAM_ADDR
Stack top address which is used in FspInit after DRAM is ready and
CAR is disabled.
config MAX_CPUS
int "Maximum number of CPUs permitted"
default 4
help
When using multi-CPU chips it is possible for U-Boot to start up
more than one CPU. The stack memory used by all of these CPUs is
pre-allocated so at present U-Boot wants to know the maximum
number of CPUs that may be present. Set this to at least as high
as the number of CPUs in your system (it uses about 4KB of RAM for
each CPU).
config SMP
bool "Enable Symmetric Multiprocessing"
default n
......@@ -241,8 +237,21 @@ config SMP
only one CPU will be enabled regardless of the number of CPUs
available.
config MAX_CPUS
int "Maximum number of CPUs permitted"
depends on SMP
default 4
help
When using multi-CPU chips it is possible for U-Boot to start up
more than one CPU. The stack memory used by all of these CPUs is
pre-allocated so at present U-Boot wants to know the maximum
number of CPUs that may be present. Set this to at least as high
as the number of CPUs in your system (it uses about 4KB of RAM for
each CPU).
config AP_STACK_SIZE
hex
depends on SMP
default 0x1000
help
Each additional CPU started by U-Boot requires its own stack. This
......@@ -270,6 +279,28 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
config HAVE_VGA_BIOS
bool "Add a VGA BIOS image"
help
Select this option if you have a VGA BIOS image that you would
like to add to your ROM.
config VGA_BIOS_FILE
string "VGA BIOS image filename"
depends on HAVE_VGA_BIOS
default "vga.bin"
help
The filename of the VGA BIOS image in the board directory.
config VGA_BIOS_ADDR
hex "VGA BIOS image location"
depends on HAVE_VGA_BIOS
default 0xfff90000
help
The location of VGA BIOS image in the SPI flash. For example, base
address of 0xfff90000 indicates that the image will be put at offset
0x90000 from the beginning of a 1MB flash device.
menu "System tables"
config GENERATE_PIRQ_TABLE
......@@ -296,6 +327,15 @@ config GENERATE_SFI_TABLE
For more information, see http://simplefirmware.org
config GENERATE_MP_TABLE
bool "Generate an MP (Multi-Processor) table"
default n
help
Generate an MP (Multi-Processor) table for this board. The MP table
provides a way for the operating system to support for symmetric
multiprocessing as well as symmetric I/O interrupt handling with
the local APIC and I/O APIC.
endmenu
config MAX_PIRQ_LINKS
......
......@@ -10,7 +10,7 @@
extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
obj-y += interrupts.o cpu.o call64.o
obj-y += interrupts.o cpu.o cpu_x86.o call64.o
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
......@@ -19,7 +19,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += irq.o lapic.o
obj-y += irq.o lapic.o ioapic.o
obj-$(CONFIG_SMP) += mp_init.o
obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o
......
......@@ -7,5 +7,4 @@
obj-y += cpu.o
obj-y += early_uart.o
obj-y += fsp_configs.o
obj-y += pci.o
obj-y += valleyview.o
......@@ -10,79 +10,11 @@
#include <cpu.h>
#include <dm.h>
#include <asm/cpu.h>
#include <asm/cpu_x86.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/turbo.h>
#ifdef CONFIG_SMP
static int enable_smis(struct udevice *cpu, void *unused)
{
return 0;
}
static struct mp_flight_record mp_steps[] = {
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
/* Wait for APs to finish initialization before proceeding. */
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
};
static int detect_num_cpus(void)
{
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);
/*
* Bay Trail 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++;
}
}
static int baytrail_init_cpus(void)
{
struct mp_params mp_params;
lapic_setup();
mp_params.num_cpus = detect_num_cpus();
mp_params.parallel_microcode_load = 0,
mp_params.flight_plan = &mp_steps[0];
mp_params.num_records = ARRAY_SIZE(mp_steps);
mp_params.microcode_pointer = 0;
if (mp_init(&mp_params)) {
printf("Warning: MP init failure\n");
return -EIO;
}
return 0;
}
#endif
int x86_init_cpus(void)
{
#ifdef CONFIG_SMP
debug("Init additional CPUs\n");
baytrail_init_cpus();
#endif
return 0;
}
static void set_max_freq(void)
{
msr_t perf_ctl;
......@@ -175,19 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
return 0;
}
static int cpu_x86_baytrail_bind(struct udevice *dev)
static int baytrail_get_count(struct udevice *dev)
{
struct cpu_platdata *plat = dev_get_parent_platdata(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);
/*
* Bay Trail 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;
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"intel,apic-id", -1);
ecx++;
}
return 0;
}
static const struct cpu_ops cpu_x86_baytrail_ops = {
.get_desc = x86_cpu_get_desc,
.get_desc = cpu_x86_get_desc,
.get_info = baytrail_get_info,
.get_count = baytrail_get_count,
};
static const struct udevice_id cpu_x86_baytrail_ids[] = {
......@@ -199,7 +150,7 @@ U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
.name = "cpu_x86_baytrail",
.id = UCLASS_CPU,
.of_match = cpu_x86_baytrail_ids,
.bind = cpu_x86_baytrail_bind,
.bind = cpu_x86_bind,
.probe = cpu_x86_baytrail_probe,
.ops = &cpu_x86_baytrail_ops,
};
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
void board_pci_setup_hose(struct pci_controller *hose)
{
hose->first_busno = 0;
hose->last_busno = 0;
/* PCI memory space */
pci_set_region(hose->regions + 0,
CONFIG_PCI_MEM_BUS,
CONFIG_PCI_MEM_PHYS,
CONFIG_PCI_MEM_SIZE,
PCI_REGION_MEM);
/* PCI IO space */
pci_set_region(hose->regions + 1,
CONFIG_PCI_IO_BUS,
CONFIG_PCI_IO_PHYS,
CONFIG_PCI_IO_SIZE,
PCI_REGION_IO);
pci_set_region(hose->regions + 2,
CONFIG_PCI_PREF_BUS,
CONFIG_PCI_PREF_PHYS,
CONFIG_PCI_PREF_SIZE,
PCI_REGION_PREFETCH);
pci_set_region(hose->regions + 3,
0,
0,
gd->ram_size < 0x80000000 ? gd->ram_size : 0x80000000,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
hose->region_count = 4;
}
......@@ -10,8 +10,8 @@ CROSS_COMPILE ?= i386-linux-
PLATFORM_CPPFLAGS += -D__I386__
# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
LDPPFLAGS += -DRESET_SEG_START=0xffff0000
LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE)
LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)"
......@@ -11,29 +11,7 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/pci.h>
DECLARE_GLOBAL_DATA_PTR;
static const struct dm_pci_ops pci_x86_ops = {
.read_config = pci_x86_read_config,
.write_config = pci_x86_write_config,
};
static const struct udevice_id pci_x86_ids[] = {
{ .compatible = "pci-x86" },
{ }
};
U_BOOT_DRIVER(pci_x86_drv) = {
.name = "pci_x86",
.id = UCLASS_PCI,
.of_match = pci_x86_ids,
.ops = &pci_x86_ops,
};
static const struct udevice_id generic_pch_ids[] = {
{ .compatible = "intel,pch" },
......
......@@ -21,12 +21,15 @@
#include <common.h>
#include <command.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/control_regs.h>
#include <asm/cpu.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/processor-flags.h>
......@@ -164,6 +167,26 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
load_fs(X86_GDT_ENTRY_32BIT_FS);
}
#ifdef CONFIG_HAVE_FSP
/*
* Setup FSP execution environment GDT
*
* Per Intel FSP external architecture specification, before calling any FSP
* APIs, we need make sure the system is in flat 32-bit mode and both the code
* and data selectors should have full 4GB access range. Here we reuse the one
* we used in arch/x86/cpu/start16.S, and reload the segement registers.
*/
void setup_fsp_gdt(void)
{
load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
load_ds(X86_GDT_ENTRY_32BIT_DS);
load_ss(X86_GDT_ENTRY_32BIT_DS);
load_es(X86_GDT_ENTRY_32BIT_DS);
load_fs(X86_GDT_ENTRY_32BIT_DS);
load_gs(X86_GDT_ENTRY_32BIT_DS);
}
#endif
int __weak x86_cleanup_before_linux(void)
{
#ifdef CONFIG_BOOTSTAGE_STASH
......@@ -330,6 +353,28 @@ int x86_cpu_init_f(void)
gd->arch.has_mtrr = has_mtrr();
}
/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
gd->pci_ram_top = 0x80000000U;
/* Configure fixed range MTRRs for some legacy regions */
if (gd->arch.has_mtrr) {
u64 mtrr_cap;
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
if (mtrr_cap & MTRR_CAP_FIX) {
/* Mark the VGA RAM area as uncacheable */
native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0);
/* Mark the PCI ROM area as uncacheable */
native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0);
/* Enable the fixed range MTRRs */
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
}
}
return 0;
}
......@@ -520,16 +565,6 @@ char *cpu_get_name(char *name)
return ptr;
}
int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
{
if (size < CPU_MAX_NAME_LEN)
return -ENOSPC;
cpu_get_name(buf);
return 0;
}
int default_print_cpuinfo(void)
{
printf("CPU: %s, vendor %s, device %xh\n",
......@@ -613,28 +648,47 @@ int last_stage_init(void)
}
#endif
__weak int x86_init_cpus(void)
#ifdef CONFIG_SMP
static int enable_smis(struct udevice *cpu, void *unused)
{
return 0;
}
int cpu_init_r(void)
static struct mp_flight_record mp_steps[] = {
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
/* Wait for APs to finish initialization before proceeding */
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
};
static int x86_mp_init(void)
{
return x86_init_cpus();
struct mp_params mp_params;
mp_params.parallel_microcode_load = 0,
mp_params.flight_plan = &mp_steps[0];
mp_params.num_records = ARRAY_SIZE(mp_steps);
mp_params.microcode_pointer = 0;
if (mp_init(&mp_params)) {
printf("Warning: MP init failure\n");
return -EIO;
}
return 0;
}
#endif
static const struct cpu_ops cpu_x86_ops = {
.get_desc = x86_cpu_get_desc,
};
__weak int x86_init_cpus(void)
{
#ifdef CONFIG_SMP
debug("Init additional CPUs\n");
x86_mp_init();
#endif
static const struct udevice_id cpu_x86_ids[] = {
{ .compatible = "cpu-x86" },
{ }
};
return 0;
}
U_BOOT_DRIVER(cpu_x86_drv) = {
.name = "cpu_x86",
.id = UCLASS_CPU,
.of_match = cpu_x86_ids,
.ops = &cpu_x86_ops,
};
int cpu_init_r(void)
{
return x86_init_cpus();
}
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <asm/cpu.h>
DECLARE_GLOBAL_DATA_PTR;
int cpu_x86_bind(struct udevice *dev)
{
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"intel,apic-id", -1);
return 0;
}
int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
{
if (size < CPU_MAX_NAME_LEN)
return -ENOSPC;
cpu_get_name(buf);
return 0;
}
static int cpu_x86_get_count(struct udevice *dev)
{
int node, cpu;
int num = 0;
node = fdt_path_offset(gd->fdt_blob, "/cpus");
if (node < 0)
return -ENOENT;
for (cpu = fdt_first_subnode(gd->fdt_blob, node);
cpu >= 0;
cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
const char *device_type;
device_type = fdt_getprop(gd->fdt_blob, cpu,
"device_type", NULL);
if (!device_type)
continue;
if (strcmp(device_type, "cpu") == 0)
num++;
}
return num;
}
static const struct cpu_ops cpu_x86_ops = {
.get_desc = cpu_x86_get_desc,
.get_count = cpu_x86_get_count,
};
static const struct udevice_id cpu_x86_ids[] = {
{ .compatible = "cpu-x86" },
{ }
};
U_BOOT_DRIVER(cpu_x86_drv) = {
.name = "cpu_x86",
.id = UCLASS_CPU,
.of_match = cpu_x86_ids,
.bind = cpu_x86_bind,
.ops = &cpu_x86_ops,
};
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/ioapic.h>
u32 io_apic_read(u32 reg)
{
writel(reg, IO_APIC_INDEX);
return readl(IO_APIC_DATA);
}
void io_apic_write(u32 reg, u32 val)
{
writel(reg, IO_APIC_INDEX);
writel(val, IO_APIC_DATA);
}
......@@ -58,17 +58,28 @@ void pirq_assign_irq(int link, u8 irq)
writeb(irq, irq_router.ibase + LINK_N2V(link, base));
}
static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus,
u8 device, u8 func, u8 pin, u8 pirq)
static struct irq_info *check_dup_entry(struct irq_info *slot_base,
int entry_num, int bus, int device)
{
struct irq_info *slot = *slotp;
struct irq_info *slot = slot_base;
int i;
for (i = 0; i < entry_num; i++) {
if (slot->bus == bus && slot->devfn == (device << 3))
break;
slot++;
}
return (i == entry_num) ? NULL : slot;
}
static inline void fill_irq_info(struct irq_info *slot, int bus, int device,
int pin, int pirq)
{
slot->bus = bus;
slot->devfn = (device << 3) | func;
slot->devfn = (device << 3) | 0;
slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base);
slot->irq[pin - 1].bitmap = irq_router.irq_mask;
(*entries)++;
(*slotp)++;
}
__weak void cpu_irq_init(void)
......@@ -84,7 +95,7 @@ static int create_pirq_routing_table(void)
int len, count;
const u32 *cell;
struct irq_routing_table *rt;
struct irq_info *slot;
struct irq_info *slot, *slot_base;
int irq_entries = 0;
int i;
int ret;
......@@ -161,13 +172,13 @@ static int create_pirq_routing_table(void)
/* Populate the PIRQ table fields */
rt->signature = PIRQ_SIGNATURE;
rt->version = PIRQ_VERSION;
rt->rtr_bus = 0;
rt->rtr_bus = PCI_BUS(irq_router.bdf);
rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) |
PCI_FUNC(irq_router.bdf);
rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
slot = rt->slots;
slot_base = rt->slots;
/* Now fill in the irq_info entries in the PIRQ table */
for (i = 0; i < count; i++) {
......@@ -181,9 +192,44 @@ static int create_pirq_routing_table(void)
i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
'A' + pr.pirq);
fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf),
slot = check_dup_entry(slot_base, irq_entries,
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
if (slot) {
debug("found entry for bus %d device %d, ",
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
if (slot->irq[pr.pin - 1].link) {
debug("skipping\n");
/*
* Sanity test on the routed PIRQ pin
*
* If they don't match, show a warning to tell
* there might be something wrong with the PIRQ
* routing information in the device tree.
*/
if (slot->irq[pr.pin - 1].link !=
LINK_N2V(pr.pirq, irq_router.link_base))
debug("WARNING: Inconsistent PIRQ routing information\n");
cell += sizeof(struct pirq_routing) /
sizeof(u32);
continue;
} else {
debug("writing INT%c\n", 'A' + pr.pin - 1);
fill_irq_info(slot, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), pr.pin, pr.pirq);
cell += sizeof(struct pirq_routing) /
sizeof(u32);
continue;
}
}