Merge git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2015-07-15 10:41:20 -04:00
commit 605e15db2b
77 changed files with 2065 additions and 1616 deletions

View file

@ -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 $@

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"intel,apic-id", -1);
/*
* 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++;
}
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,
};

View file

@ -1,46 +0,0 @@
/*
* 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;
}

View file

@ -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)"

View file

@ -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" },

View file

@ -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,8 +648,43 @@ int last_stage_init(void)
}
#endif
#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 x86_mp_init(void)
{
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
__weak int x86_init_cpus(void)
{
#ifdef CONFIG_SMP
debug("Init additional CPUs\n");
x86_mp_init();
#endif
return 0;
}
@ -622,19 +692,3 @@ int cpu_init_r(void)
{
return x86_init_cpus();
}
static const struct cpu_ops cpu_x86_ops = {
.get_desc = x86_cpu_get_desc,
};
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,
.ops = &cpu_x86_ops,
};

76
arch/x86/cpu/cpu_x86.c Normal file
View file

@ -0,0 +1,76 @@
/*
* 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,
};

21
arch/x86/cpu/ioapic.c Normal file
View file

@ -0,0 +1,21 @@
/*
* 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);
}

View file

@ -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;
}
}
slot = slot_base + irq_entries;
fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
pr.pin, pr.pirq);
irq_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}

View file

@ -95,7 +95,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_BOOTBLOCK_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_LAPIC
select CPU_MICROCODE_IN_CBFS

View file

@ -13,12 +13,12 @@
#include <asm/acpi.h>
#include <asm/cpu.h>
#include <asm/lapic.h>
#include <asm/lapic_def.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/processor.h>
#include <asm/speedstep.h>
#include <asm/turbo.h>
#include <asm/arch/bd82x6x.h>
#include <asm/arch/model_206ax.h>
static void enable_vmx(void)

View file

@ -8,50 +8,153 @@
*/
#include <common.h>
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/lapic.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
#include <asm/post.h>
unsigned long lapic_read(unsigned long reg)
{
return readl(LAPIC_DEFAULT_BASE + reg);
}
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
/*
* Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
*
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument.
*/
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
: "=q" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
}
return x;
}
void lapic_write(unsigned long reg, unsigned long v)
{
(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
}
void enable_lapic(void)
{
msr_t msr;
msr = msr_read(MSR_IA32_APICBASE);
msr.hi &= 0xffffff00;
msr.lo |= MSR_IA32_APICBASE_ENABLE;
msr.lo &= ~MSR_IA32_APICBASE_BASE;
msr.lo |= LAPIC_DEFAULT_BASE;
msr_write(MSR_IA32_APICBASE, msr);
}
void disable_lapic(void)
{
msr_t msr;
msr = msr_read(MSR_IA32_APICBASE);
msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
msr_write(MSR_IA32_APICBASE, msr);
}
unsigned long lapicid(void)
{
return lapic_read(LAPIC_ID) >> 24;
}
static void lapic_wait_icr_idle(void)
{
do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
}
int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
{
int timeout;
unsigned long status;
int result;
lapic_wait_icr_idle();
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
result = -1;
if (status == LAPIC_ICR_RR_VALID) {
*pvalue = lapic_read(LAPIC_RRR);
result = 0;
}
return result;
}
void lapic_setup(void)
{
#if NEED_LAPIC == 1
#ifdef CONFIG_SMP
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Set Task Priority to 'accept all' */
lapic_write(LAPIC_TASKPRI,
lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
#else /* !NEED_LLAPIC */
#else /* !CONFIG_SMP */
/* Only Pentium Pro and later have those MSR stuff */
debug("Disabling local apic: ");
disable_lapic();
#endif /* !NEED_LAPIC */
#endif /* CONFIG_SMP */
debug("done.\n");
post_code(POST_LAPIC);
}

View file

@ -16,12 +16,17 @@
#include <asm/interrupt.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/processor.h>
#include <asm/sipi.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#include <linux/linkage.h>
/* Total CPUs include BSP */
static int num_cpus;
/* This also needs to match the sipi.S assembly code for saved MSR encoding */
struct saved_msr {
uint32_t index;
@ -56,6 +61,13 @@ static inline void release_barrier(atomic_t *b)
atomic_set(b, 1);
}
static inline void stop_this_cpu(void)
{
/* Called by an AP when it is ready to halt and wait for a new task */
for (;;)
cpu_hlt();
}
/* Returns 1 if timeout waiting for APs. 0 if target APs found */
static int wait_for_aps(atomic_t *val, int target, int total_delay,
int delay_step)
@ -314,9 +326,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
/* Send INIT IPI to all but self */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
debug("Waiting for 10ms after sending INIT.\n");
mdelay(10);
@ -331,9 +343,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 1st SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@ -356,9 +368,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 2nd SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@ -383,7 +395,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
int ret = 0;
const int timeout_us = 100000;
const int step_us = 100;
int num_aps = mp_params->num_cpus - 1;
int num_aps = num_cpus - 1;
for (i = 0; i < mp_params->num_records; i++) {
struct mp_flight_record *rec = &mp_params->flight_plan[i];
@ -415,7 +427,7 @@ static int init_bsp(struct udevice **devp)
cpu_get_name(processor_name);
debug("CPU: %s.\n", processor_name);
enable_lapic();
lapic_setup();
apic_id = lapicid();
ret = find_cpu_by_apid_id(apic_id, devp);
@ -451,7 +463,16 @@ int mp_init(struct mp_params *p)
return -1;
}
ret = check_cpu_devices(p->num_cpus);
num_cpus = cpu_get_count(cpu);
if (num_cpus < 0) {
debug("Cannot get number of CPUs: err=%d\n", num_cpus);
return num_cpus;
}
if (num_cpus < 2)
debug("Warning: Only 1 CPU is detected\n");
ret = check_cpu_devices(num_cpus);
if (ret)
debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
@ -471,7 +492,7 @@ int mp_init(struct mp_params *p)
wbinvd();
/* Start the APs providing number of APs and the cpus_entered field */
num_aps = p->num_cpus - 1;
num_aps = num_cpus - 1;
ret = start_aps(num_aps, ap_count);
if (ret) {
mdelay(1000);

View file

@ -38,4 +38,8 @@ config CMC_ADDR
The default base address of 0xfffb0000 indicates that the binary must
be located at offset 0xb0000 from the beginning of a 1MB flash device.
config CPU_ADDR_BITS
int
default 32
endif

View file

@ -69,17 +69,18 @@ void cpu_irq_init(void)
* Route TunnelCreek PCI device interrupt pin to PIRQ
*
* Since PCIe downstream ports received INTx are routed to PIRQ
* A/B/C/D directly and not configurable, we route internal PCI
* device's INTx to PIRQ E/F/G/H.
* A/B/C/D directly and not configurable, we have to route PCIe
* root ports' INTx to PIRQ A/B/C/D as well. For other devices
* on TunneCreek, route them to PIRQ E/F/G/H.
*/
writew(PIRQE, &rcba->d02ir);
writew(PIRQF, &rcba->d03ir);
writew(PIRQG, &rcba->d27ir);
writew(PIRQH, &rcba->d31ir);
writew(PIRQE, &rcba->d23ir);
writew(PIRQF, &rcba->d24ir);
writew(PIRQG, &rcba->d25ir);
writew(PIRQH, &rcba->d26ir);
writew(PIRQA, &rcba->d23ir);
writew(PIRQB, &rcba->d24ir);
writew(PIRQC, &rcba->d25ir);
writew(PIRQD, &rcba->d26ir);
}
int arch_misc_init(void)

View file

@ -116,12 +116,16 @@ car_init_ret:
rep stosb
#ifdef CONFIG_HAVE_FSP
test %esi, %esi
jz skip_hob
/* Store HOB list */
movl %esp, %edx
addl $GD_HOB_LIST, %edx
movl %esi, (%edx)
#endif
skip_hob:
#endif
/* Setup first parameter to setup_gdt, pointer to global_data */
movl %esp, %eax

View file

@ -71,11 +71,12 @@ idt_ptr:
*/
gdt_ptr:
.word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
.long BOOT_SEG + gdt /* base */
.long BOOT_SEG + gdt_rom /* base */
/* Some CPUs are picky about GDT alignment... */
.align 16
gdt:
.globl gdt_rom
gdt_rom:
/*
* The GDT table ...
*

View file

@ -10,6 +10,7 @@
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/include/ "rtc.dtsi"
/ {
model = "Intel Crown Bay";
@ -23,6 +24,26 @@
silent_console = <0>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <1>;
intel,apic-id = <1>;
};
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
@ -148,10 +169,22 @@
/* TunnelCreek PCI devices */
PCI_BDF(0, 2, 0) INTA PIRQE
PCI_BDF(0, 3, 0) INTA PIRQF
PCI_BDF(0, 23, 0) INTA PIRQE
PCI_BDF(0, 24, 0) INTA PIRQF
PCI_BDF(0, 25, 0) INTA PIRQG
PCI_BDF(0, 26, 0) INTA PIRQH
PCI_BDF(0, 23, 0) INTA PIRQA
PCI_BDF(0, 23, 0) INTB PIRQB
PCI_BDF(0, 23, 0) INTC PIRQC
PCI_BDF(0, 23, 0) INTD PIRQD
PCI_BDF(0, 24, 0) INTA PIRQB
PCI_BDF(0, 24, 0) INTB PIRQC
PCI_BDF(0, 24, 0) INTC PIRQD
PCI_BDF(0, 24, 0) INTD PIRQA
PCI_BDF(0, 25, 0) INTA PIRQC
PCI_BDF(0, 25, 0) INTB PIRQD
PCI_BDF(0, 25, 0) INTC PIRQA
PCI_BDF(0, 25, 0) INTD PIRQB
PCI_BDF(0, 26, 0) INTA PIRQD
PCI_BDF(0, 26, 0) INTB PIRQA
PCI_BDF(0, 26, 0) INTC PIRQB
PCI_BDF(0, 26, 0) INTD PIRQC
PCI_BDF(0, 27, 0) INTA PIRQG
/*
* Topcliff PCI devices
@ -159,29 +192,29 @@
* Note on the Crown Bay board, Topcliff chipset
* is connected to TunnelCreek PCIe port 0, so
* its bus number is 1 for its PCIe port and 2
* for its PCI devices per U-Boot currnet PCI
* for its PCI devices per U-Boot current PCI
* bus enumeration algorithm.
*/
PCI_BDF(1, 0, 0) INTA PIRQA
PCI_BDF(2, 0, 1) INTA PIRQA
PCI_BDF(2, 0, 2) INTA PIRQA
PCI_BDF(2, 2, 0) INTB PIRQB
PCI_BDF(2, 2, 1) INTB PIRQB
PCI_BDF(2, 2, 2) INTB PIRQB
PCI_BDF(2, 2, 3) INTB PIRQB
PCI_BDF(2, 2, 4) INTB PIRQB
PCI_BDF(2, 2, 0) INTB PIRQD
PCI_BDF(2, 2, 1) INTB PIRQD
PCI_BDF(2, 2, 2) INTB PIRQD
PCI_BDF(2, 2, 3) INTB PIRQD
PCI_BDF(2, 2, 4) INTB PIRQD
PCI_BDF(2, 4, 0) INTC PIRQC
PCI_BDF(2, 4, 1) INTC PIRQC
PCI_BDF(2, 6, 0) INTD PIRQD
PCI_BDF(2, 6, 0) INTD PIRQB
PCI_BDF(2, 8, 0) INTA PIRQA
PCI_BDF(2, 8, 1) INTA PIRQA
PCI_BDF(2, 8, 2) INTA PIRQA
PCI_BDF(2, 8, 3) INTA PIRQA
PCI_BDF(2, 10, 0) INTB PIRQB
PCI_BDF(2, 10, 1) INTB PIRQB
PCI_BDF(2, 10, 2) INTB PIRQB
PCI_BDF(2, 10, 3) INTB PIRQB
PCI_BDF(2, 10, 4) INTB PIRQB
PCI_BDF(2, 10, 0) INTB PIRQD
PCI_BDF(2, 10, 1) INTB PIRQD
PCI_BDF(2, 10, 2) INTB PIRQD
PCI_BDF(2, 10, 3) INTB PIRQD
PCI_BDF(2, 10, 4) INTB PIRQD
PCI_BDF(2, 12, 0) INTC PIRQC
PCI_BDF(2, 12, 1) INTC PIRQC
PCI_BDF(2, 12, 2) INTC PIRQC

View file

@ -111,6 +111,16 @@
};
pci {
compatible = "intel,pci-baytrail", "pci-x86";
#address-cells = <3>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000
0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000
0x01000000 0x0 0x2000 0x2000 0 0xe000>;
};
spi {
#address-cells = <1>;
#size-cells = <0>;

6
arch/x86/dts/rtc.dtsi Normal file
View file

@ -0,0 +1,6 @@
/ {
rtc {
compatible = "motorola,mc146818";
reg = <0x70 2>;
};
};

View file

@ -16,7 +16,19 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node);
int bd82x6x_init(void);
struct x86_cpu_priv;
/**
* struct x86_cpu_priv - Information about a single CPU
*
* @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
* just a number representing the CPU core
*
* TODO: Move this to driver model once lifecycle is understood
*/
struct x86_cpu_priv {
int apic_id;
int start_err;
};
int model_206ax_init(struct x86_cpu_priv *cpu);
#endif

View file

@ -196,20 +196,6 @@ const char *cpu_vendor_name(int vendor);
*/
char *cpu_get_name(char *name);
/**
*
* x86_cpu_get_desc() - Get a description string for an x86 CPU
*
* This uses cpu_get_name() and is suitable to use as the get_desc() method for
* the CPU uclass.
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int x86_cpu_get_desc(struct udevice *dev, char *buf, int size);
/**
* cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
*

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ASM_CPU_X86_H
#define _ASM_CPU_X86_H
/**
* cpu_x86_bind() - Bind an x86 CPU with the driver
*
* This updates cpu device's platform data with information from device tree,
* like the processor local apic id.
*
* @dev: Device to check (UCLASS_CPU)
* @return 0 always
*/
int cpu_x86_bind(struct udevice *dev);
/**
* cpu_x86_get_desc() - Get a description string for an x86 CPU
*
* This uses cpu_get_name() and is suitable to use as the get_desc() method for
* the CPU uclass.
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
#endif /* _ASM_CPU_X86_H */

View file

@ -10,29 +10,33 @@
#define __ASM_IOAPIC_H
#define IO_APIC_ADDR 0xfec00000
#define IO_APIC_INDEX IO_APIC_ADDR
/* Direct addressed register */
#define IO_APIC_INDEX (IO_APIC_ADDR + 0x00)
#define IO_APIC_DATA (IO_APIC_ADDR + 0x10)
#define IO_APIC_INTERRUPTS 24
#define ALL (0xff << 24)
#define NONE 0
#define DISABLED (1 << 16)
#define ENABLED (0 << 16)
#define TRIGGER_EDGE (0 << 15)
#define TRIGGER_LEVEL (1 << 15)
#define POLARITY_HIGH (0 << 13)
#define POLARITY_LOW (1 << 13)
#define PHYSICAL_DEST (0 << 11)
#define LOGICAL_DEST (1 << 11)
#define ExtINT (7 << 8)
#define NMI (4 << 8)
#define SMI (2 << 8)
#define INT (1 << 8)
/* Indirect addressed register offset */
#define IO_APIC_ID 0x00
#define IO_APIC_VER 0x01
u32 io_apic_read(u32 ioapic_base, u32 reg);
void io_apic_write(u32 ioapic_base, u32 reg, u32 value);
void set_ioapic_id(u32 ioapic_base, u8 ioapic_id);
void setup_ioapic(u32 ioapic_base, u8 ioapic_id);
void clear_ioapic(u32 ioapic_base);
/**
* io_apic_read() - Read I/O APIC register
*
* This routine reads I/O APIC indirect addressed register.
*
* @reg: address of indirect addressed register
* @return: register value to read
*/
u32 io_apic_read(u32 reg);
/**
* io_apic_write() - Write I/O APIC register
*
* This routine writes I/O APIC indirect addressed register.
*
* @reg: address of indirect addressed register
* @val: register value to write
*/
void io_apic_write(u32 reg, u32 val);
#endif

View file

@ -1,5 +1,5 @@
/*
* From Coreboot file of same name
* From coreboot file of same name
*
* Copyright (C) 2014 Google, Inc
*
@ -9,171 +9,70 @@
#ifndef _ARCH_ASM_LAPIC_H
#define _ARCH_ASM_LAPIC_H
#include <asm/io.h>
#include <asm/lapic_def.h>
#include <asm/msr.h>
#include <asm/processor.h>
#define LAPIC_DEFAULT_BASE 0xfee00000
/* See if I need to initialize the local apic */
#if CONFIG_SMP || CONFIG_IOAPIC
# define NEED_LAPIC 1
#else
# define NEED_LAPIC 0
#endif
#define LAPIC_ID 0x020
#define LAPIC_LVR 0x030
static inline __attribute__((always_inline))
unsigned long lapic_read(unsigned long reg)
{
return readl(LAPIC_DEFAULT_BASE + reg);
}
#define LAPIC_TASKPRI 0x080
#define LAPIC_TPRI_MASK 0xff
static inline __attribute__((always_inline))
void lapic_write(unsigned long reg, unsigned long val)
{
writel(val, LAPIC_DEFAULT_BASE + reg);
}
#define LAPIC_RRR 0x0c0
static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
{
do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
}
#define LAPIC_SPIV 0x0f0
#define LAPIC_SPIV_ENABLE 0x100
static inline void enable_lapic(void)
{
msr_t msr;
#define LAPIC_ICR 0x300
#define LAPIC_DEST_SELF 0x40000
#define LAPIC_DEST_ALLINC 0x80000
#define LAPIC_DEST_ALLBUT 0xc0000
#define LAPIC_ICR_RR_MASK 0x30000
#define LAPIC_ICR_RR_INVALID 0x00000
#define LAPIC_ICR_RR_INPROG 0x10000
#define LAPIC_ICR_RR_VALID 0x20000
#define LAPIC_INT_LEVELTRIG 0x08000
#define LAPIC_INT_ASSERT 0x04000
#define LAPIC_ICR_BUSY 0x01000
#define LAPIC_DEST_LOGICAL 0x00800
#define LAPIC_DM_FIXED 0x00000
#define LAPIC_DM_LOWEST 0x00100
#define LAPIC_DM_SMI 0x00200
#define LAPIC_DM_REMRD 0x00300
#define LAPIC_DM_NMI 0x00400
#define LAPIC_DM_INIT 0x00500
#define LAPIC_DM_STARTUP 0x00600
#define LAPIC_DM_EXTINT 0x00700
#define LAPIC_VECTOR_MASK 0x000ff
msr = msr_read(LAPIC_BASE_MSR);
msr.hi &= 0xffffff00;
msr.lo |= LAPIC_BASE_MSR_ENABLE;
msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
msr.lo |= LAPIC_DEFAULT_BASE;
msr_write(LAPIC_BASE_MSR, msr);
}
#define LAPIC_ICR2 0x310
#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff)
#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
static inline void disable_lapic(void)
{
msr_t msr;
#define LAPIC_LVT0 0x350
#define LAPIC_LVT1 0x360
#define LAPIC_LVT_MASKED (1 << 16)
#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
#define LAPIC_LVT_REMOTE_IRR (1 << 14)
#define LAPIC_INPUT_POLARITY (1 << 13)
#define LAPIC_SEND_PENDING (1 << 12)
#define LAPIC_LVT_RESERVED_1 (1 << 11)
#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~(1 << 11);
msr_write(LAPIC_BASE_MSR, msr);
}
unsigned long lapic_read(unsigned long reg);
static inline __attribute__((always_inline)) unsigned long lapicid(void)
{
return lapic_read(LAPIC_ID) >> 24;
}
void lapic_write(unsigned long reg, unsigned long v);
#if !CONFIG_AP_IN_SIPI_WAIT
/* If we need to go back to sipi wait, we use the long non-inlined version of
* this function in lapic_cpu_init.c
*/
static inline __attribute__((always_inline)) void stop_this_cpu(void)
{
/* Called by an AP when it is ready to halt and wait for a new task */
for (;;)
cpu_hlt();
}
#else
void stop_this_cpu(void);
#endif
void enable_lapic(void);
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
sizeof(*(ptr))))
void disable_lapic(void);
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
/*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument. --ANK
*/
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
: "=q" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
}
return x;
}
static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
{
(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
}
#ifdef X86_GOOD_APIC
# define FORCE_READ_AROUND_WRITE 0
# define lapic_read_around(x) lapic_read(x)
# define lapic_write_around(x, y) lapic_write((x), (y))
#else
# define FORCE_READ_AROUND_WRITE 1
# define lapic_read_around(x) lapic_read(x)
# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
#endif
static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
{
int timeout;
unsigned long status;
int result;
lapic_wait_icr_idle();
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
result = -1;
if (status == LAPIC_ICR_RR_VALID) {
*pvalue = lapic_read(LAPIC_RRR);
result = 0;
}
return result;
}
unsigned long lapicid(void);
int lapic_remote_read(int apicid, int reg, unsigned long *pvalue);
void lapic_setup(void);
#if CONFIG_SMP
struct device;
int start_cpu(struct device *cpu);
#endif /* CONFIG_SMP */
int boot_cpu(void);
/**
* struct x86_cpu_priv - Information about a single CPU
*
* @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
* just a number representing the CPU core
*
* TODO: Move this to driver model once lifecycle is understood
*/
struct x86_cpu_priv {
int apic_id;
int start_err;
};
#endif

View file

@ -1,101 +0,0 @@
/*
* Taken from the Coreboot file of the same name
*
* (C) Copyright 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef _ASM_LAPIC_DEF_H
#define _ASM_LAPIC_DEF_H
#define LAPIC_BASE_MSR 0x1B
#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8)
#define LAPIC_BASE_MSR_ENABLE (1 << 11)
#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000
#define LOCAL_APIC_ADDR 0xfee00000
#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR
#define LAPIC_ID 0x020
#define LAPIC_LVR 0x030
#define LAPIC_TASKPRI 0x80
#define LAPIC_TPRI_MASK 0xFF
#define LAPIC_ARBID 0x090
#define LAPIC_RRR 0x0C0
#define LAPIC_SVR 0x0f0
#define LAPIC_SPIV 0x0f0
#define LAPIC_SPIV_ENABLE 0x100
#define LAPIC_ESR 0x280
#define LAPIC_ESR_SEND_CS 0x00001
#define LAPIC_ESR_RECV_CS 0x00002
#define LAPIC_ESR_SEND_ACC 0x00004
#define LAPIC_ESR_RECV_ACC 0x00008
#define LAPIC_ESR_SENDILL 0x00020
#define LAPIC_ESR_RECVILL 0x00040
#define LAPIC_ESR_ILLREGA 0x00080
#define LAPIC_ICR 0x300
#define LAPIC_DEST_SELF 0x40000
#define LAPIC_DEST_ALLINC 0x80000
#define LAPIC_DEST_ALLBUT 0xC0000
#define LAPIC_ICR_RR_MASK 0x30000
#define LAPIC_ICR_RR_INVALID 0x00000
#define LAPIC_ICR_RR_INPROG 0x10000
#define LAPIC_ICR_RR_VALID 0x20000
#define LAPIC_INT_LEVELTRIG 0x08000
#define LAPIC_INT_ASSERT 0x04000
#define LAPIC_ICR_BUSY 0x01000
#define LAPIC_DEST_LOGICAL 0x00800
#define LAPIC_DM_FIXED 0x00000
#define LAPIC_DM_LOWEST 0x00100
#define LAPIC_DM_SMI 0x00200
#define LAPIC_DM_REMRD 0x00300
#define LAPIC_DM_NMI 0x00400
#define LAPIC_DM_INIT 0x00500
#define LAPIC_DM_STARTUP 0x00600
#define LAPIC_DM_EXTINT 0x00700
#define LAPIC_VECTOR_MASK 0x000FF
#define LAPIC_ICR2 0x310
#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
#define LAPIC_LVTT 0x320
#define LAPIC_LVTPC 0x340
#define LAPIC_LVT0 0x350
#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18)
#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
#define SET_LAPIC_TIMER_BASE(x) (((x) << 18))
#define LAPIC_TIMER_BASE_CLKIN 0x0
#define LAPIC_TIMER_BASE_TMBASE 0x1
#define LAPIC_TIMER_BASE_DIV 0x2
#define LAPIC_LVT_TIMER_PERIODIC (1 << 17)
#define LAPIC_LVT_MASKED (1 << 16)
#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
#define LAPIC_LVT_REMOTE_IRR (1 << 14)
#define LAPIC_INPUT_POLARITY (1 << 13)
#define LAPIC_SEND_PENDING (1 << 12)
#define LAPIC_LVT_RESERVED_1 (1 << 11)
#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8))
#define LAPIC_MODE_FIXED 0x0
#define LAPIC_MODE_NMI 0x4
#define LAPIC_MODE_EXINT 0x7
#define LAPIC_LVT1 0x360
#define LAPIC_LVTERR 0x370
#define LAPIC_TMICT 0x380
#define LAPIC_TMCCT 0x390
#define LAPIC_TDCR 0x3E0
#define LAPIC_TDR_DIV_TMBASE (1 << 2)
#define LAPIC_TDR_DIV_1 0xB
#define LAPIC_TDR_DIV_2 0x0
#define LAPIC_TDR_DIV_4 0x1
#define LAPIC_TDR_DIV_8 0x2
#define LAPIC_TDR_DIV_16 0x3
#define LAPIC_TDR_DIV_32 0x8
#define LAPIC_TDR_DIV_64 0x9
#define LAPIC_TDR_DIV_128 0xA
#endif

View file

@ -59,7 +59,6 @@ struct mp_flight_record {
* SMM support.
*/
struct mp_params {
int num_cpus; /* Total cpus include BSP */
int parallel_microcode_load;
const void *microcode_pointer;
/* Flight plan for APs and BSP */

View file

@ -0,0 +1,444 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ASM_MPSPEC_H
#define __ASM_MPSPEC_H
/*
* Structure definitions for SMP machines following the
* Intel MultiProcessor Specification 1.4
*/
#define MPSPEC_V14 4
#define MPF_SIGNATURE "_MP_"
struct mp_floating_table {
char mpf_signature[4]; /* "_MP_" */
u32 mpf_physptr; /* Configuration table address */
u8 mpf_length; /* Our length (paragraphs) */
u8 mpf_spec; /* Specification version */
u8 mpf_checksum; /* Checksum (makes sum 0) */
u8 mpf_feature1; /* Predefined or Unique configuration? */
u8 mpf_feature2; /* Bit7 set for IMCR/PIC */
u8 mpf_feature3; /* Unused (0) */
u8 mpf_feature4; /* Unused (0) */
u8 mpf_feature5; /* Unused (0) */
};
#define MPC_SIGNATURE "PCMP"
struct mp_config_table {
char mpc_signature[4]; /* "PCMP" */
u16 mpc_length; /* Size of table */
u8 mpc_spec; /* Specification version */
u8 mpc_checksum; /* Checksum (makes sum 0) */
char mpc_oem[8]; /* OEM ID */
char mpc_product[12]; /* Product ID */
u32 mpc_oemptr; /* OEM table address */
u16 mpc_oemsize; /* OEM table size */
u16 mpc_entry_count; /* Number of entries in the table */
u32 mpc_lapic; /* Local APIC address */
u16 mpe_length; /* Extended table size */
u8 mpe_checksum; /* Extended table checksum */
u8 reserved;
};
/* Base MP configuration table entry types */
enum mp_base_config_entry_type {
MP_PROCESSOR,
MP_BUS,
MP_IOAPIC,
MP_INTSRC,
MP_LINTSRC
};
#define MPC_CPU_EN (1 << 0)
#define MPC_CPU_BP (1 << 1)
struct mpc_config_processor {
u8 mpc_type;
u8 mpc_apicid;
u8 mpc_apicver;
u8 mpc_cpuflag;
u32 mpc_cpusignature;
u32 mpc_cpufeature;
u32 mpc_reserved[2];
};
#define BUSTYPE_CBUS "CBUS "
#define BUSTYPE_CBUSII "CBUSII"
#define BUSTYPE_EISA "EISA "
#define BUSTYPE_FUTURE "FUTURE"
#define BUSTYPE_INTERN "INTERN"
#define BUSTYPE_ISA "ISA "
#define BUSTYPE_MBI "MBI "
#define BUSTYPE_MBII "MBII "
#define BUSTYPE_MCA "MCA "
#define BUSTYPE_MPI "MPI "
#define BUSTYPE_MPSA "MPSA "
#define BUSTYPE_NUBUS "NUBUS "
#define BUSTYPE_PCI "PCI "
#define BUSTYPE_PCMCIA "PCMCIA"
#define BUSTYPE_TC "TC "
#define BUSTYPE_VL "VL "
#define BUSTYPE_VME "VME "
#define BUSTYPE_XPRESS "XPRESS"
struct mpc_config_bus {
u8 mpc_type;
u8 mpc_busid;
u8 mpc_bustype[6];
};
#define MPC_APIC_USABLE (1 << 0)
struct mpc_config_ioapic {
u8 mpc_type;
u8 mpc_apicid;
u8 mpc_apicver;
u8 mpc_flags;
u32 mpc_apicaddr;
};
enum mp_irq_source_types {
MP_INT,
MP_NMI,
MP_SMI,
MP_EXTINT
};
#define MP_IRQ_POLARITY_DEFAULT 0x0
#define MP_IRQ_POLARITY_HIGH 0x1
#define MP_IRQ_POLARITY_LOW 0x3
#define MP_IRQ_POLARITY_MASK 0x3
#define MP_IRQ_TRIGGER_DEFAULT 0x0
#define MP_IRQ_TRIGGER_EDGE 0x4
#define MP_IRQ_TRIGGER_LEVEL 0xc
#define MP_IRQ_TRIGGER_MASK 0xc
#define MP_APIC_ALL 0xff
struct mpc_config_intsrc {
u8 mpc_type;
u8 mpc_irqtype;
u16 mpc_irqflag;
u8 mpc_srcbus;
u8 mpc_srcbusirq;
u8 mpc_dstapic;
u8 mpc_dstirq;
};
struct mpc_config_lintsrc {
u8 mpc_type;
u8 mpc_irqtype;
u16 mpc_irqflag;
u8 mpc_srcbusid;
u8 mpc_srcbusirq;
u8 mpc_destapic;
u8 mpc_destlint;
};
/* Extended MP configuration table entry types */
enum mp_ext_config_entry_type {
MPE_SYSTEM_ADDRESS_SPACE = 128,
MPE_BUS_HIERARCHY,
MPE_COMPAT_ADDRESS_SPACE
};
struct mp_ext_config {
u8 mpe_type;
u8 mpe_length;
};
#define ADDRESS_TYPE_IO 0
#define ADDRESS_TYPE_MEM 1
#define ADDRESS_TYPE_PREFETCH 2
struct mp_ext_system_address_space {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_addr_type;
u32 mpe_addr_base_low;
u32 mpe_addr_base_high;
u32 mpe_addr_length_low;
u32 mpe_addr_length_high;
};
#define BUS_SUBTRACTIVE_DECODE (1 << 0)
struct mp_ext_bus_hierarchy {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_bus_info;
u8 mpe_parent_busid;
u8 reserved[3];
};
#define ADDRESS_RANGE_ADD 0
#define ADDRESS_RANGE_SUBTRACT 1
/*
* X100 - X3FF
* X500 - X7FF
* X900 - XBFF
* XD00 - XFFF
*/
#define RANGE_LIST_IO_ISA 0
/*
* X3B0 - X3BB
* X3C0 - X3DF
* X7B0 - X7BB
* X7C0 - X7DF
* XBB0 - XBBB
* XBC0 - XBDF
* XFB0 - XFBB
* XFC0 - XCDF
*/
#define RANGE_LIST_IO_VGA 1
struct mp_ext_compat_address_space {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_addr_modifier;
u32 mpe_range_list;
};
/**
* mp_next_mpc_entry() - Compute MP configuration table end to be used as
* next base table entry start address
*
* This computes the end address of current MP configuration table, without
* counting any extended configuration table entry.
*
* @mc: configuration table header address
* @return: configuration table end address
*/
static inline u32 mp_next_mpc_entry(struct mp_config_table *mc)
{
return (u32)mc + mc->mpc_length;
}
/**
* mp_add_mpc_entry() - Add a base MP configuration table entry
*
* This adds the base MP configuration table entry size with
* added base table entry length and increases entry count by 1.
*
* @mc: configuration table header address
* @length: length of the added table entry
*/
static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length)
{
mc->mpc_length += length;
mc->mpc_entry_count++;
}
/**
* mp_next_mpe_entry() - Compute MP configuration table end to be used as
* next extended table entry start address
*
* This computes the end address of current MP configuration table,
* including any extended configuration table entry.
*
* @mc: configuration table header address
* @return: configuration table end address
*/
static inline u32 mp_next_mpe_entry(struct mp_config_table *mc)
{
return (u32)mc + mc->mpc_length + mc->mpe_length;
}
/**
* mp_add_mpe_entry() - Add an extended MP configuration table entry
*
* This adds the extended MP configuration table entry size with
* added extended table entry length.
*
* @mc: configuration table header address
* @mpe: extended table entry base address
*/
static inline void mp_add_mpe_entry(struct mp_config_table *mc,
struct mp_ext_config *mpe)
{
mc->mpe_length += mpe->mpe_length;
}
/**
* mp_write_floating_table() - Write the MP floating table
*
* This writes the MP floating table, and points MP configuration table
* to its end address so that MP configuration table follows immediately
* after the floating table.
*
* @mf: MP floating table base address
* @return: MP configuration table header address
*/
struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf);
/**
* mp_config_table_init() - Initialize the MP configuration table header
*
* This populates the MP configuration table header with valid bits.
*
* @mc: MP configuration table header address
*/
void mp_config_table_init(struct mp_config_table *mc);
/**
* mp_write_processor() - Write a processor entry
*
* This writes a processor entry to the configuration table.
*
* @mc: MP configuration table header address
*/
void mp_write_processor(struct mp_config_table *mc);
/**
* mp_write_bus() - Write a bus entry
*
* This writes a bus entry to the configuration table.
*
* @mc: MP configuration table header address
* @id: bus id
* @bustype: bus type name
*/
void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype);
/**
* mp_write_ioapic() - Write an I/O APIC entry
*
* This writes an I/O APIC entry to the configuration table.
*
* @mc: MP configuration table header address
* @id: I/O APIC id
* @ver: I/O APIC version
* @apicaddr: I/O APIC address
*/
void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr);
/**
* mp_write_intsrc() - Write an I/O interrupt assignment entry
*
* This writes an I/O interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @irqflag: IRQ flag (level/trigger)
* @srcbus: source bus id where the interrupt comes from
* @srcbusirq: IRQ number mapped on the source bus
* @dstapic: destination I/O APIC id where the interrupt goes to
* @dstirq: destination I/O APIC pin where the interrupt goes to
*/
void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int dstapic, int dstirq);
/**
* mp_write_pci_intsrc() - Write a PCI interrupt assignment entry
*
* This writes a PCI interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @srcbus: PCI bus number where the interrupt comes from
* @dev: device number on the PCI bus
* @pin: PCI interrupt pin (INT A/B/C/D)
* @dstapic: destination I/O APIC id where the interrupt goes to
* @dstirq: destination I/O APIC pin where the interrupt goes to
*/
void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
int srcbus, int dev, int pin, int dstapic, int dstirq);
/**
* mp_write_lintsrc() - Write a local interrupt assignment entry
*
* This writes a local interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @irqflag: IRQ flag (level/trigger)
* @srcbus: PCI bus number where the interrupt comes from
* @srcbusirq: IRQ number mapped on the source bus
* @dstapic: destination local APIC id where the interrupt goes to
* @destlint: destination local APIC pin where the interrupt goes to
*/
void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int destapic, int destlint);
/**
* mp_write_address_space() - Write a system address space entry
*
* This writes a system address space entry to the configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id for the bus where system address space is mapped
* @addr_type: system address type
* @addr_base_low: starting address low
* @addr_base_high: starting address high
* @addr_length_low: address length low
* @addr_length_high: address length high
*/
void mp_write_address_space(struct mp_config_table *mc,
int busid, int addr_type,
u32 addr_base_low, u32 addr_base_high,
u32 addr_length_low, u32 addr_length_high);
/**
* mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry
*
* This writes a bus hierarchy descriptor entry to the configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id
* @bus_info: bit0 indicates if the bus is a subtractive decode bus
* @parent_busid: parent bus id
*/
void mp_write_bus_hierarchy(struct mp_config_table *mc,
int busid, int bus_info, int parent_busid);
/**
* mp_write_compat_address_space() - Write a compat bus address space entry
*
* This writes a compatibility bus address space modifier entry to the
* configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id
* @addr_modifier: add or subtract to predefined address range list
* @range_list: list of predefined address space ranges
*/
void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
int addr_modifier, u32 range_list);
/**
* mptable_finalize() - Finalize the MP table
*
* This finalizes the MP table by calculating required checksums.
*
* @mc: MP configuration table header address
* @return: MP table end address
*/
u32 mptable_finalize(struct mp_config_table *mc);
/**
* write_mp_table() - Write MP table
*
* This writes MP table at a given address.
*
* @addr: start address to write MP table
* @return: end address of MP table
*/
u32 write_mp_table(u32 addr);
#endif /* __ASM_MPSPEC_H */

View file

@ -21,6 +21,11 @@
#define MTRR_CAP_MSR 0x0fe
#define MTRR_DEF_TYPE_MSR 0x2ff
#define MTRR_CAP_SMRR (1 << 11)
#define MTRR_CAP_WC (1 << 10)
#define MTRR_CAP_FIX (1 << 8)
#define MTRR_CAP_VCNT_MASK 0xff
#define MTRR_DEF_TYPE_EN (1 << 11)
#define MTRR_DEF_TYPE_FIX_EN (1 << 10)
@ -38,17 +43,17 @@
#define RANGES_PER_FIXED_MTRR 8
#define NUM_FIXED_RANGES (NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
#define MTRR_FIX_64K_00000_MSR 0x250
#define MTRR_FIX_16K_80000_MSR 0x258
#define MTRR_FIX_16K_A0000_MSR 0x259
#define MTRR_FIX_4K_C0000_MSR 0x268
#define MTRR_FIX_4K_C8000_MSR 0x269
#define MTRR_FIX_4K_D0000_MSR 0x26a
#define MTRR_FIX_4K_D8000_MSR 0x26b
#define MTRR_FIX_4K_E0000_MSR 0x26c
#define MTRR_FIX_4K_E8000_MSR 0x26d
#define MTRR_FIX_4K_F0000_MSR 0x26e
#define MTRR_FIX_4K_F8000_MSR 0x26f
#define MTRR_FIX_64K_00000_MSR 0x250
#define MTRR_FIX_16K_80000_MSR 0x258
#define MTRR_FIX_16K_A0000_MSR 0x259
#define MTRR_FIX_4K_C0000_MSR 0x268
#define MTRR_FIX_4K_C8000_MSR 0x269
#define MTRR_FIX_4K_D0000_MSR 0x26a
#define MTRR_FIX_4K_D8000_MSR 0x26b
#define MTRR_FIX_4K_E0000_MSR 0x26c
#define MTRR_FIX_4K_E8000_MSR 0x26d
#define MTRR_FIX_4K_F0000_MSR 0x26e
#define MTRR_FIX_4K_F8000_MSR 0x26f
#if !defined(__ASSEMBLER__)

View file

@ -27,6 +27,20 @@
*/
u8 table_compute_checksum(void *v, int len);
/**
* table_fill_string() - Fill a string with pad in the configuration table
*
* This fills a string in the configuration table. It copies number of bytes
* from the source string, and if source string length is shorter than the
* required size to copy, pad the table string with the given pad character.
*
* @dest: where to fill a string
* @src: where to copy from
* @n: number of bytes to copy
* @pad: character to pad the remaining bytes
*/
void table_fill_string(char *dest, const char *src, size_t n, char pad);
/**
* write_tables() - Write x86 configuration tables
*

View file

@ -8,12 +8,19 @@
#ifndef _U_BOOT_I386_H_
#define _U_BOOT_I386_H_ 1
extern char gdt_rom[];
/* cpu/.../cpu.c */
int arch_cpu_init(void);
int x86_cpu_init_f(void);
int cpu_init_f(void);
void init_gd(gd_t *id, u64 *gdt_addr);
void setup_gdt(gd_t *id, u64 *gdt_addr);
/*
* Setup FSP execution environment GDT to use the one we used in
* arch/x86/cpu/start16.S and reload the segment registers.
*/
void setup_fsp_gdt(void);
int init_cache(void);
int cleanup_before_linux(void);
@ -49,6 +56,9 @@ u32 isa_map_rom(u32 bus_addr, int size);
/* arch/x86/lib/... */
int video_bios_init(void);
/* arch/x86/lib/fsp/... */
int x86_fsp_init(void);
void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
void board_init_f_r(void) __attribute__ ((noreturn));

View file

@ -38,5 +38,6 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
ulong *load_addressp);
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
unsigned long initrd_addr, unsigned long initrd_size);
void setup_video(struct screen_info *screen_info);
#endif

View file

@ -15,6 +15,7 @@ obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += lpc-uclass.o
obj-y += mpspec.o
obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o

View file

@ -246,6 +246,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
push %fs
push %gs
/* Save real mode SS */
movw %ss, %cs:__realmode_ss
/* Clear DF to not break ABI assumptions */
cld
@ -258,12 +261,29 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
enter_protected_mode
/*
* Now we are in protected mode. We need compute the right ESP based
* on saved real mode SS otherwise interrupt_handler() won't get
* correct parameters from the stack.
*/
movzwl %cs:__realmode_ss, %ecx
shll $4, %ecx
addl %ecx, %esp
/* Call the C interrupt handler */
movl $interrupt_handler, %eax
call *%eax
/* Restore real mode ESP based on saved SS */
movzwl %cs:__realmode_ss, %ecx
shll $4, %ecx
subl %ecx, %esp
enter_real_mode
/* Restore real mode SS */
movw %cs:__realmode_ss, %ss
/*
* Restore all registers, including those manipulated by the C
* handler
@ -276,6 +296,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
popal
iret
__realmode_ss = PTR_TO_REAL_MODE(.)
.word 0
.globl asm_realmode_code_size
asm_realmode_code_size:
.long . - asm_realmode_code

View file

@ -161,15 +161,7 @@ int int1a_handler(void)
bus = M.x86.R_EBX >> 8;
reg = M.x86.R_EDI;
dev = PCI_BDF(bus, devfn >> 3, devfn & 7);
if (!dev) {
debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func,
bus, devfn);
/* Or are we supposed to return PCIBIOS_NODEV? */
M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
M.x86.R_EAX |= PCIBIOS_BADREG;
retval = 0;
return retval;
}
switch (func) {
case 0xb108: /* Read Config Byte */
byte = x86_pci_read_config8(dev, reg);

View file

@ -37,7 +37,8 @@ static int do_mtrr_list(void)
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
valid ? "Y" : "N", type, base, mask, size);
valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
mask & ~MTRR_PHYS_MASK_VALID, size);
}
return 0;

View file

@ -56,28 +56,10 @@ temp_ram_init_ret:
/* stack grows down from top of CAR */
movl %edx, %esp
subl $4, %esp
/*
* TODO:
*
* According to FSP architecture spec, the fsp_init() will not return
* to its caller, instead it requires the bootloader to provide a
* so-called continuation function to pass into the FSP as a parameter
* of fsp_init, and fsp_init() will call that continuation function
* directly.
*
* The call to fsp_init() may need to be moved out of the car_init()
* to cpu_init_f() with the help of some inline assembly codes.
* Note there is another issue that fsp_init() will setup another stack
* using the fsp_init parameter stack_top after DRAM is initialized,
* which means any data on the previous stack (on the CAR) gets lost
* (ie: U-Boot global_data). FSP is supposed to support such scenario,
* however it does not work. This should be revisited in the future.
*/
movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
xorl %edx, %edx
xorl %ecx, %ecx
call fsp_init
xor %esi, %esi
jmp car_init_done
.global fsp_init_done
fsp_init_done:
@ -86,6 +68,8 @@ fsp_init_done:
* Save eax to esi temporarily.
*/
movl %eax, %esi
car_init_done:
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.

View file

@ -46,3 +46,11 @@ void board_final_cleanup(void)
return;
}
int x86_fsp_init(void)
{
if (!gd->arch.hob_list)
fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL);
return 0;
}

View file

@ -173,6 +173,9 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
post_code(POST_PRE_MRC);
/* Load GDT for FSP */
setup_fsp_gdt();
/*
* Use ASM code to ensure the register value in EAX & ECX
* will be passed into BlContinuationFunc

382
arch/x86/lib/mpspec.c Normal file
View file

@ -0,0 +1,382 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/arch/x86/boot/mpspec.c
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <asm/cpu.h>
#include <asm/irq.h>
#include <asm/ioapic.h>
#include <asm/lapic.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
#include <dm/uclass-internal.h>
DECLARE_GLOBAL_DATA_PTR;
struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf)
{
u32 mc;
memcpy(mf->mpf_signature, MPF_SIGNATURE, 4);
mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table);
mf->mpf_length = 1;
mf->mpf_spec = MPSPEC_V14;
mf->mpf_checksum = 0;
/* We don't use the default configuration table */
mf->mpf_feature1 = 0;
/* Indicate that virtual wire mode is always implemented */
mf->mpf_feature2 = 0;
mf->mpf_feature3 = 0;
mf->mpf_feature4 = 0;
mf->mpf_feature5 = 0;
mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16);
mc = (u32)mf + sizeof(struct mp_floating_table);
return (struct mp_config_table *)mc;
}
void mp_config_table_init(struct mp_config_table *mc)
{
memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
mc->mpc_length = sizeof(struct mp_config_table);
mc->mpc_spec = MPSPEC_V14;
mc->mpc_checksum = 0;
mc->mpc_oemptr = 0;
mc->mpc_oemsize = 0;
mc->mpc_entry_count = 0;
mc->mpc_lapic = LAPIC_DEFAULT_BASE;
mc->mpe_length = 0;
mc->mpe_checksum = 0;
mc->reserved = 0;
/* The oem/product id fields are exactly 8/12 bytes long */
table_fill_string(mc->mpc_oem, CONFIG_SYS_VENDOR, 8, ' ');
table_fill_string(mc->mpc_product, CONFIG_SYS_BOARD, 12, ' ');
}
void mp_write_processor(struct mp_config_table *mc)
{
struct mpc_config_processor *mpc;
struct udevice *dev;
u8 boot_apicid, apicver;
u32 cpusignature, cpufeature;
struct cpuid_result result;
boot_apicid = lapicid();
apicver = lapic_read(LAPIC_LVR) & 0xff;
result = cpuid(1);
cpusignature = result.eax;
cpufeature = result.edx;
for (uclass_find_first_device(UCLASS_CPU, &dev);
dev;
uclass_find_next_device(&dev)) {
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
u8 cpuflag = MPC_CPU_EN;
if (!device_active(dev))
continue;
mpc = (struct mpc_config_processor *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_PROCESSOR;
mpc->mpc_apicid = plat->cpu_id;
mpc->mpc_apicver = apicver;
if (boot_apicid == plat->cpu_id)
cpuflag |= MPC_CPU_BP;
mpc->mpc_cpuflag = cpuflag;
mpc->mpc_cpusignature = cpusignature;
mpc->mpc_cpufeature = cpufeature;
mpc->mpc_reserved[0] = 0;
mpc->mpc_reserved[1] = 0;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
}
void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype)
{
struct mpc_config_bus *mpc;
mpc = (struct mpc_config_bus *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_BUS;
mpc->mpc_busid = id;
memcpy(mpc->mpc_bustype, bustype, 6);
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr)
{
struct mpc_config_ioapic *mpc;
mpc = (struct mpc_config_ioapic *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_IOAPIC;
mpc->mpc_apicid = id;
mpc->mpc_apicver = ver;
mpc->mpc_flags = MPC_APIC_USABLE;
mpc->mpc_apicaddr = apicaddr;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int dstapic, int dstirq)
{
struct mpc_config_intsrc *mpc;
mpc = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_INTSRC;
mpc->mpc_irqtype = irqtype;
mpc->mpc_irqflag = irqflag;
mpc->mpc_srcbus = srcbus;
mpc->mpc_srcbusirq = srcbusirq;
mpc->mpc_dstapic = dstapic;
mpc->mpc_dstirq = dstirq;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
int srcbus, int dev, int pin, int dstapic, int dstirq)
{
u8 srcbusirq = (dev << 2) | (pin - 1);
mp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW,
srcbus, srcbusirq, dstapic, dstirq);
}
void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int destapic, int destlint)
{
struct mpc_config_lintsrc *mpc;
mpc = (struct mpc_config_lintsrc *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_LINTSRC;
mpc->mpc_irqtype = irqtype;
mpc->mpc_irqflag = irqflag;
mpc->mpc_srcbusid = srcbus;
mpc->mpc_srcbusirq = srcbusirq;
mpc->mpc_destapic = destapic;
mpc->mpc_destlint = destlint;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_address_space(struct mp_config_table *mc,
int busid, int addr_type,
u32 addr_base_low, u32 addr_base_high,
u32 addr_length_low, u32 addr_length_high)
{
struct mp_ext_system_address_space *mpe;
mpe = (struct mp_ext_system_address_space *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_addr_type = addr_type;
mpe->mpe_addr_base_low = addr_base_low;
mpe->mpe_addr_base_high = addr_base_high;
mpe->mpe_addr_length_low = addr_length_low;
mpe->mpe_addr_length_high = addr_length_high;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
void mp_write_bus_hierarchy(struct mp_config_table *mc,
int busid, int bus_info, int parent_busid)
{
struct mp_ext_bus_hierarchy *mpe;
mpe = (struct mp_ext_bus_hierarchy *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_BUS_HIERARCHY;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_bus_info = bus_info;
mpe->mpe_parent_busid = parent_busid;
mpe->reserved[0] = 0;
mpe->reserved[1] = 0;
mpe->reserved[2] = 0;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
int addr_modifier, u32 range_list)
{
struct mp_ext_compat_address_space *mpe;
mpe = (struct mp_ext_compat_address_space *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_COMPAT_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_addr_modifier = addr_modifier;
mpe->mpe_range_list = range_list;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
u32 mptable_finalize(struct mp_config_table *mc)
{
u32 end;
mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc),
mc->mpe_length);
mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length);
end = mp_next_mpe_entry(mc);
debug("Write the MP table at: %x - %x\n", (u32)mc, end);
return end;
}
static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa,
int apicid, int external_int2)
{
int i;
mp_write_intsrc(mc, external_int2 ? MP_INT : MP_EXTINT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, apicid, 0);
mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 1, apicid, 1);
mp_write_intsrc(mc, external_int2 ? MP_EXTINT : MP_INT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, apicid, 2);
for (i = 3; i < 16; i++)
mp_write_intsrc(mc, MP_INT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, i, apicid, i);
}
/*
* Check duplicated I/O interrupt assignment table entry, to make sure
* there is only one entry with the given bus, device and interrupt pin.
*/
static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base,
int entry_num, int bus, int device, int pin)
{
struct mpc_config_intsrc *intsrc = intsrc_base;
int i;
for (i = 0; i < entry_num; i++) {
if (intsrc->mpc_srcbus == bus &&
intsrc->mpc_srcbusirq == ((device << 2) | (pin - 1)))
break;
intsrc++;
}
return (i == entry_num) ? false : true;
}
static int mptable_add_intsrc(struct mp_config_table *mc,
int bus_isa, int apicid)
{
struct mpc_config_intsrc *intsrc_base;
int intsrc_entries = 0;
const void *blob = gd->fdt_blob;
int node;
int len, count;
const u32 *cell;
int i;
/* Legacy Interrupts */
debug("Writing ISA IRQs\n");
mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
/* Get I/O interrupt information from device tree */
node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER);
if (node < 0) {
debug("%s: Cannot find irq router node\n", __func__);
return -ENOENT;
}
cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
if (!cell)
return -ENOENT;
if ((len % sizeof(struct pirq_routing)) == 0)
count = len / sizeof(struct pirq_routing);
else
return -EINVAL;
intsrc_base = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
for (i = 0; i < count; i++) {
struct pirq_routing pr;
pr.bdf = fdt_addr_to_cpu(cell[0]);
pr.pin = fdt_addr_to_cpu(cell[1]);
pr.pirq = fdt_addr_to_cpu(cell[2]);
if (check_dup_entry(intsrc_base, intsrc_entries,
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) {
debug("found entry for bus %d device %d INT%c, skipping\n",
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
'A' + pr.pin - 1);
cell += sizeof(struct pirq_routing) / sizeof(u32);
continue;
}
/* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */
mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), pr.pin, apicid,
pr.pirq + 16);
intsrc_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}
return 0;
}
static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa)
{
mp_write_lintsrc(mc, MP_EXTINT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, MP_APIC_ALL, 0);
mp_write_lintsrc(mc, MP_NMI,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, MP_APIC_ALL, 1);
}
u32 write_mp_table(u32 addr)
{
struct mp_config_table *mc;
int ioapic_id, ioapic_ver;
int bus_isa = 0xff;
int ret;
u32 end;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);
/* Write floating table */
mc = mp_write_floating_table((struct mp_floating_table *)addr);
/* Write configuration table header */
mp_config_table_init(mc);
/* Write processor entry */
mp_write_processor(mc);
/* Write bus entry */
mp_write_bus(mc, bus_isa, BUSTYPE_ISA);
/* Write I/O APIC entry */
ioapic_id = io_apic_read(IO_APIC_ID) >> 24;
ioapic_ver = io_apic_read(IO_APIC_VER) & 0xff;
mp_write_ioapic(mc, ioapic_id, ioapic_ver, IO_APIC_ADDR);
/* Write I/O interrupt assignment entry */
ret = mptable_add_intsrc(mc, bus_isa, ioapic_id);
if (ret)
debug("Failed to write I/O interrupt assignment table\n");
/* Write local interrupt assignment entry */
mptable_add_lintsrc(mc, bus_isa);
/* Finalize the MP table */
end = mptable_finalize(mc);
return end;
}

View file

@ -6,6 +6,7 @@
#include <common.h>
#include <asm/sfi.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
u8 table_compute_checksum(void *v, int len)
@ -20,6 +21,20 @@ u8 table_compute_checksum(void *v, int len)
return checksum;
}
void table_fill_string(char *dest, const char *src, size_t n, char pad)
{
int start, len;
int i;
strncpy(dest, src, n);
/* Fill the remaining bytes with pad */
len = strlen(src);
start = len < n ? len : n;
for (i = start; i < n; i++)
dest[i] = pad;
}
void write_tables(void)
{
u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR;
@ -32,4 +47,8 @@ void write_tables(void)
rom_table_end = write_sfi_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
#ifdef CONFIG_GENERATE_MP_TABLE
rom_table_end = write_mp_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
}

View file

@ -273,6 +273,8 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
build_command_line(cmd_line, auto_boot);
}
setup_video(&setup_base->screen_info);
return 0;
}

View file

@ -22,7 +22,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
select HAVE_ACPI_RESUME
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
config PCIE_ECAM_BASE

View file

@ -23,7 +23,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
select HAVE_ACPI_RESUME
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
config SYS_CAR_ADDR

View file

@ -753,6 +753,9 @@ static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,
#endif
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
x86_fsp_init,
#endif
#ifdef CONFIG_TRACE
trace_early_init,
#endif

View file

@ -9,6 +9,7 @@
#include <command.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
static const char *cpu_feature_name[CPU_FEAT_COUNT] = {
"L1 cache",

View file

@ -37,7 +37,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int old_bus __maybe_unused;
/* switch to correct I2C bus */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
struct udevice *dev;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
@ -57,7 +57,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
case 2: /* set date & time */
if (strcmp(argv[1],"reset") == 0) {
puts ("Reset RTC...\n");
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_reset(dev);
if (!rcode)
rcode = dm_rtc_set(dev, &default_tm);
@ -69,7 +69,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
puts("## Failed to set date after RTC reset\n");
} else {
/* initialize tm with current time */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
@ -81,7 +81,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
break;
}
/* and write to RTC */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_set(dev, &tm);
#else
rcode = rtc_set(&tm);
@ -96,7 +96,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
/* FALL TROUGH */
case 1: /* get date & time */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
@ -120,7 +120,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/* switch back to original I2C bus */
#ifdef CONFIG_SYS_I2C
i2c_set_bus_num(old_bus);
#elif !defined(CONFIG_DM_I2C)
#elif !defined(CONFIG_DM_RTC)
I2C_SET_BUS(old_bus);
#endif

View file

@ -303,8 +303,12 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
else
ret = spi_flash_write(flash, offset, len, buf);
printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset,
read ? "Read" : "Written", ret ? "ERROR" : "OK");
printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset,
read ? "Read" : "Written");
if (ret)
printf("ERROR %d\n", ret);
else
printf("OK\n");
}
unmap_physmem(buf, len);

View file

@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
CONFIG_TARGET_CHROMEBOOK_LINK=y
CONFIG_HAVE_MRC=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set

View file

@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebox_panther"
CONFIG_TARGET_CHROMEBOX_PANTHER=y
CONFIG_HAVE_MRC=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set

View file

@ -2,7 +2,12 @@ CONFIG_X86=y
CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="crownbay"
CONFIG_TARGET_CROWNBAY=y
CONFIG_SMP=y
CONFIG_MAX_CPUS=2
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
@ -11,6 +16,10 @@ CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_CPU=y
CONFIG_SPI_FLASH=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_DM_RTC=y
CONFIG_USE_PRIVATE_LIBGCC=y
CONFIG_SYS_VSNPRINTF=y

View file

@ -4,6 +4,7 @@ CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
CONFIG_TARGET_MINNOWMAX=y
CONFIG_HAVE_INTEL_ME=y
CONFIG_SMP=y
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_SFI_TABLE=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_IMLS is not set
@ -15,6 +16,7 @@ CONFIG_BOOTSTAGE_REPORT=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_CPU=y
CONFIG_DM_PCI=y
CONFIG_SPI_FLASH=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y

View file

@ -79,7 +79,7 @@ Find the following files:
* ./northbridge/intel/sandybridge/systemagent-r6.bin
The 3rd one should be renamed to mrc.bin.
As for the video ROM, you can get it here [3].
As for the video ROM, you can get it here [3] and rename it to vga.bin.
Make sure all these binary blobs are put in the board directory.
Now you can build U-Boot and obtain u-boot.rom:
@ -113,6 +113,10 @@ binary using any hex editor (eg: bvi). Go to the offset 0x1fcd8 of the FSP
binary, change the following five bytes values from orginally E8 42 FF FF FF
to B8 00 80 0B 00.
As for the video ROM, you need manually extract it from the Intel provided
BIOS for Crown Bay here [6], using the AMI MMTool [7]. Check PCI option ROM
ID 8086:4108, extract and save it as vga.bin in the board directory.
Now you can build U-Boot and obtain u-boot.rom
$ make crownbay_defconfig
@ -160,6 +164,31 @@ Now you can build U-Boot and obtain u-boot.rom
$ make minnowmax_defconfig
$ make all
Checksums are as follows (but note that newer versions will invalidate this):
$ md5sum -b board/intel/minnowmax/*.bin
ffda9a3b94df5b74323afb328d51e6b4 board/intel/minnowmax/descriptor.bin
69f65b9a580246291d20d08cbef9d7c5 board/intel/minnowmax/fsp.bin
894a97d371544ec21de9c3e8e1716c4b board/intel/minnowmax/me.bin
a2588537da387da592a27219d56e9962 board/intel/minnowmax/vga.bin
The ROM image is broken up into these parts:
Offset Description Controlling config
------------------------------------------------------------
000000 descriptor.bin Hard-coded to 0 in ifdtool
001000 me.bin Set by the descriptor
500000 <spare>
700000 u-boot-dtb.bin CONFIG_SYS_TEXT_BASE
790000 vga.bin CONFIG_X86_OPTION_ROM_ADDR
7c0000 fsp.bin CONFIG_FSP_ADDR
7f8000 <spare> (depends on size of fsp.bin)
7fe000 Environment CONFIG_ENV_OFFSET
7ff800 U-Boot 16-bit boot CONFIG_SYS_X86_START16
Overall ROM image size is controlled by CONFIG_ROM_SIZE.
Intel Galileo instructions:
Only one binary blob is needed for Remote Management Unit (RMU) within Intel
@ -254,10 +283,21 @@ If you want to check both consoles, use '-serial stdio'.
CPU Microcode
-------------
Modern CPUs usually require a special bit stream called microcode [6] to be
Modern CPUs usually require a special bit stream called microcode [8] to be
loaded on the processor after power up in order to function properly. U-Boot
has already integrated these as hex dumps in the source tree.
SMP Support
-----------
On a multicore system, U-Boot is executed on the bootstrap processor (BSP).
Additional application processors (AP) can be brought up by U-Boot. In order to
have an SMP kernel to discover all of the available processors, U-Boot needs to
prepare configuration tables which contain the multi-CPUs information before
loading the OS kernel. Currently U-Boot supports generating two types of tables
for SMP, called Simple Firmware Interface (SFI) [9] and Multi-Processor (MP)
[10] tables. The writing of these two tables are controlled by two Kconfig
options GENERATE_SFI_TABLE and GENERATE_MP_TABLE.
Driver Model
------------
x86 has been converted to use driver model for serial and GPIO.
@ -361,4 +401,8 @@ References
[3] http://www.coreboot.org/~stepan/pci8086,0166.rom
[4] http://www.intel.com/content/www/us/en/embedded/design-tools/evaluation-platforms/atom-e660-eg20t-development-kit.html
[5] http://www.intel.com/fsp
[6] http://en.wikipedia.org/wiki/Microcode
[6] http://www.intel.com/content/www/us/en/secure/intelligent-systems/privileged/e6xx-35-b1-cmc22211.html
[7] http://www.ami.com/products/bios-uefi-tools-and-utilities/bios-uefi-utilities/
[8] http://en.wikipedia.org/wiki/Microcode
[9] http://simplefirmware.org
[10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm

View file

@ -6,7 +6,6 @@
#
obj-$(CONFIG_SCSI_AHCI) += ahci.o
obj-$(CONFIG_ATA_PIIX) += ata_piix.o
obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
obj-$(CONFIG_FSL_SATA) += fsl_sata.o
obj-$(CONFIG_IDE_FTIDE020) += ftide020.o

View file

@ -1,717 +0,0 @@
/*
* Copyright (C) Procsys. All rights reserved.
* Author: Mushtaq Khan <mushtaq_k@procsys.com>
* <mushtaqk_921@yahoo.co.in>
*
* SPDX-License-Identifier: GPL-2.0+
*
* with the reference to ata_piix driver in kernel 2.4.32
*/
/*
* This file contains SATA controller and SATA drive initialization functions
*/
#include <common.h>
#include <asm/io.h>
#include <pci.h>
#include <command.h>
#include <config.h>
#include <asm/byteorder.h>
#include <part.h>
#include <ide.h>
#include <ata.h>
#include <sata.h>
#define DEBUG_SATA 0 /* For debug prints set DEBUG_SATA to 1 */
#define SATA_DECL
#define DRV_DECL /* For file specific declarations */
#include "ata_piix.h"
/* Macros realted to PCI */
#define PCI_SATA_BUS 0x00
#define PCI_SATA_DEV 0x1f
#define PCI_SATA_FUNC 0x02
#define PCI_SATA_BASE1 0x10
#define PCI_SATA_BASE2 0x14
#define PCI_SATA_BASE3 0x18
#define PCI_SATA_BASE4 0x1c
#define PCI_SATA_BASE5 0x20
#define PCI_PMR 0x90
#define PCI_PI 0x09
#define PCI_PCS 0x92
#define PCI_DMA_CTL 0x48
#define PORT_PRESENT (1<<0)
#define PORT_ENABLED (1<<4)
u32 bdf;
u32 iobase1; /* Primary cmd block */
u32 iobase2; /* Primary ctl block */
u32 iobase3; /* Sec cmd block */
u32 iobase4; /* sec ctl block */
u32 iobase5; /* BMDMA*/
int pci_sata_init(void)
{
u32 bus = PCI_SATA_BUS;
u32 dev = PCI_SATA_DEV;
u32 fun = PCI_SATA_FUNC;
u16 cmd = 0;
u8 lat = 0, pcibios_max_latency = 0xff;
u8 pmr; /* Port mapping reg */
u8 pi; /* Prgming Interface reg */
bdf = PCI_BDF(bus, dev, fun);
pci_read_config_dword(bdf, PCI_SATA_BASE1, &iobase1);
pci_read_config_dword(bdf, PCI_SATA_BASE2, &iobase2);
pci_read_config_dword(bdf, PCI_SATA_BASE3, &iobase3);
pci_read_config_dword(bdf, PCI_SATA_BASE4, &iobase4);
pci_read_config_dword(bdf, PCI_SATA_BASE5, &iobase5);
if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) ||
(iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) ||
(iobase5 == 0xFFFFFFFF)) {
/* ERROR */
printf("error no base addr for SATA controller\n");
return 1;
}
iobase1 &= 0xFFFFFFFE;
iobase2 &= 0xFFFFFFFE;
iobase3 &= 0xFFFFFFFE;
iobase4 &= 0xFFFFFFFE;
iobase5 &= 0xFFFFFFFE;
/* check for mode */
pci_read_config_byte(bdf, PCI_PMR, &pmr);
if (pmr > 1) {
puts("combined mode not supported\n");
return 1;
}
pci_read_config_byte(bdf, PCI_PI, &pi);
if ((pi & 0x05) != 0x05) {
puts("Sata is in Legacy mode\n");
return 1;
} else
puts("sata is in Native mode\n");
/* MASTER CFG AND IO CFG */
pci_read_config_word(bdf, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
pci_write_config_word(bdf, PCI_COMMAND, cmd);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
return 0;
}
int sata_bus_probe(int port_no)
{
int orig_mask, mask;
u16 pcs;
mask = (PORT_PRESENT << port_no);
pci_read_config_word(bdf, PCI_PCS, &pcs);
orig_mask = (int) pcs & 0xff;
if ((orig_mask & mask) != mask)
return 0;
else
return 1;
}
int init_sata(int dev)
{
static int done;
u8 i, rv = 0;
if (!done)
done = 1;
else
return 0;
rv = pci_sata_init();
if (rv == 1) {
puts("pci initialization failed\n");
return 1;
}
port[0].port_no = 0;
port[0].ioaddr.cmd_addr = iobase1;
port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr =
iobase2 | ATA_PCI_CTL_OFS;
port[0].ioaddr.bmdma_addr = iobase5;
port[1].port_no = 1;
port[1].ioaddr.cmd_addr = iobase3;
port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr =
iobase4 | ATA_PCI_CTL_OFS;
port[1].ioaddr.bmdma_addr = iobase5 + 0x8;
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++)
sata_port(&port[i].ioaddr);
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
if (!(sata_bus_probe(i))) {
port[i].port_state = 0;
printf("SATA#%d port is not present\n", i);
} else {
printf("SATA#%d port is present\n", i);
if (sata_bus_softreset(i))
port[i].port_state = 0;
else
port[i].port_state = 1;
}
}
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
u8 j, devno;
if (port[i].port_state == 0)
continue;
for (j = 0; j < CONFIG_SYS_SATA_DEVS_PER_BUS; j++) {
sata_identify(i, j);
set_Feature_cmd(i, j);
devno = i * CONFIG_SYS_SATA_DEVS_PER_BUS + j;
if ((sata_dev_desc[devno].lba > 0) &&
(sata_dev_desc[devno].blksz > 0)) {
dev_print(&sata_dev_desc[devno]);
/* initialize partition type */
init_part(&sata_dev_desc[devno]);
}
}
}
return 0;
}
int reset_sata(int dev)
{
return 0;
}
static inline u8 sata_inb(unsigned long ioaddr)
{
return inb(ioaddr);
}
static inline void sata_outb(unsigned char val, unsigned long ioaddr)
{
outb(val, ioaddr);
}
static void output_data(struct sata_ioports *ioaddr, ulong * sect_buf,
int words)
{
outsw(ioaddr->data_addr, sect_buf, words << 1);
}
static int input_data(struct sata_ioports *ioaddr, ulong * sect_buf, int words)
{
insw(ioaddr->data_addr, sect_buf, words << 1);
return 0;
}
static void sata_cpy(unsigned char *dst, unsigned char *src, unsigned int len)
{
unsigned char *end, *last;
last = dst;
end = src + len - 1;
/* reserve space for '\0' */
if (len < 2)
goto OUT;
/* skip leading white space */
while ((*src) && (src < end) && (*src == ' '))
++src;
/* copy string, omitting trailing white space */
while ((*src) && (src < end)) {
*dst++ = *src;
if (*src++ != ' ')
last = dst;
}
OUT:
*last = '\0';
}
int sata_bus_softreset(int num)
{
u8 dev = 0, status = 0, i;
port[num].dev_mask = 0;
for (i = 0; i < CONFIG_SYS_SATA_DEVS_PER_BUS; i++) {
if (!(sata_devchk(&port[num].ioaddr, i))) {
debug("dev_chk failed for dev#%d\n", i);
} else {
port[num].dev_mask |= (1 << i);
debug("dev_chk passed for dev#%d\n", i);
}
}
if (!(port[num].dev_mask)) {
printf("no devices on port%d\n", num);
return 1;
}
dev_select(&port[num].ioaddr, dev);
port[num].ctl_reg = 0x08; /* Default value of control reg */
sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
udelay(10);
sata_outb(port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
udelay(10);
sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
/*
* spec mandates ">= 2ms" before checking status.
* We wait 150ms, because that was the magic delay used for
* ATAPI devices in Hale Landis's ATADRVR, for the period of time
* between when the ATA command register is written, and then
* status is checked. Because waiting for "a while" before
* checking status is fine, post SRST, we perform this magic
* delay here as well.
*/
mdelay(150);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 300);
while ((status & ATA_BUSY)) {
mdelay(100);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3);
}
if (status & ATA_BUSY)
printf("ata%u is slow to respond,plz be patient\n", num);
while ((status & ATA_BUSY)) {
mdelay(100);
status = sata_chk_status(&port[num].ioaddr);
}
if (status & ATA_BUSY) {
printf("ata%u failed to respond : bus reset failed\n", num);
return 1;
}
return 0;
}
void sata_identify(int num, int dev)
{
u8 cmd = 0, status = 0;
u8 devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev;
u16 iobuf[ATA_SECT_SIZE];
u64 n_sectors = 0;
u8 mask = 0;
memset(iobuf, 0, sizeof(iobuf));
hd_driveid_t *iop = (hd_driveid_t *) iobuf;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
printf("dev%d is not present on port#%d\n", dev, num);
return;
}
printf("port=%d dev=%d\n", num, dev);
dev_select(&port[num].ioaddr, dev);
status = 0;
cmd = ATA_CMD_IDENT; /* Device Identify Command */
sata_outb(cmd, port[num].ioaddr.command_addr);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(10);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 1000);
if (status & ATA_ERR) {
puts("\ndevice not responding\n");
port[num].dev_mask &= ~mask;
return;
}
input_data(&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS);
debug("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x"
"86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49],
iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86],
iobuf[87], iobuf[88]);
/* we require LBA and DMA support (bits 8 & 9 of word 49) */
if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf))
debug("ata%u: no dma/lba\n", num);
ata_dump_id(iobuf);
if (ata_id_has_lba48(iobuf))
n_sectors = ata_id_u64(iobuf, 100);
else
n_sectors = ata_id_u32(iobuf, 60);
debug("no. of sectors %u\n", ata_id_u64(iobuf, 100));
debug("no. of sectors %u\n", ata_id_u32(iobuf, 60));
if (n_sectors == 0) {
port[num].dev_mask &= ~mask;
return;
}
sata_cpy((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev,
sizeof(sata_dev_desc[devno].revision));
sata_cpy((unsigned char *)sata_dev_desc[devno].vendor, iop->model,
sizeof(sata_dev_desc[devno].vendor));
sata_cpy((unsigned char *)sata_dev_desc[devno].product, iop->serial_no,
sizeof(sata_dev_desc[devno].product));
strswab(sata_dev_desc[devno].revision);
strswab(sata_dev_desc[devno].vendor);
if ((iop->config & 0x0080) == 0x0080)
sata_dev_desc[devno].removable = 1;
else
sata_dev_desc[devno].removable = 0;
sata_dev_desc[devno].lba = iop->lba_capacity;
debug("lba=0x%x", sata_dev_desc[devno].lba);
#ifdef CONFIG_LBA48
if (iop->command_set_2 & 0x0400) {
sata_dev_desc[devno].lba48 = 1;
lba = (unsigned long long) iop->lba48_capacity[0] |
((unsigned long long) iop->lba48_capacity[1] << 16) |
((unsigned long long) iop->lba48_capacity[2] << 32) |
((unsigned long long) iop->lba48_capacity[3] << 48);
} else {
sata_dev_desc[devno].lba48 = 0;
}
#endif
/* assuming HD */
sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
sata_dev_desc[devno].blksz = ATA_BLOCKSIZE;
sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz);
sata_dev_desc[devno].lun = 0; /* just to fill something in... */
}
void set_Feature_cmd(int num, int dev)
{
u8 mask = 0x00, status = 0;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
debug("dev%d is not present on port#%d\n", dev, num);
return;
}
dev_select(&port[num].ioaddr, dev);
sata_outb(SETFEATURES_XFER, port[num].ioaddr.feature_addr);
sata_outb(XFER_PIO_4, port[num].ioaddr.nsect_addr);
sata_outb(0, port[num].ioaddr.lbal_addr);
sata_outb(0, port[num].ioaddr.lbam_addr);
sata_outb(0, port[num].ioaddr.lbah_addr);
sata_outb(ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_SETF, port[num].ioaddr.command_addr);
udelay(50);
mdelay(150);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 5000);
if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) {
printf("Error : status 0x%02x\n", status);
port[num].dev_mask &= ~mask;
}
}
void sata_port(struct sata_ioports *ioport)
{
ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA;
ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR;
ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE;
ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT;
ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL;
ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM;
ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH;
ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE;
ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS;
ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD;
}
int sata_devchk(struct sata_ioports *ioaddr, int dev)
{
u8 nsect, lbal;
dev_select(ioaddr, dev);
sata_outb(0x55, ioaddr->nsect_addr);
sata_outb(0xaa, ioaddr->lbal_addr);
sata_outb(0xaa, ioaddr->nsect_addr);
sata_outb(0x55, ioaddr->lbal_addr);
sata_outb(0x55, ioaddr->nsect_addr);
sata_outb(0xaa, ioaddr->lbal_addr);
nsect = sata_inb(ioaddr->nsect_addr);
lbal = sata_inb(ioaddr->lbal_addr);
if ((nsect == 0x55) && (lbal == 0xaa))
return 1; /* we found a device */
else
return 0; /* nothing found */
}
void dev_select(struct sata_ioports *ioaddr, int dev)
{
u8 tmp = 0;
if (dev == 0)
tmp = ATA_DEVICE_OBS;
else
tmp = ATA_DEVICE_OBS | ATA_DEV1;
sata_outb(tmp, ioaddr->device_addr);
sata_inb(ioaddr->altstatus_addr);
udelay(5);
}
u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max)
{
u8 status;
do {
udelay(1000);
status = sata_chk_status(ioaddr);
max--;
} while ((status & bits) && (max > 0));
return status;
}
u8 sata_chk_status(struct sata_ioports *ioaddr)
{
return sata_inb(ioaddr->status_addr);
}
ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
u8 dev = 0, num = 0, mask = 0, status = 0;
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
/* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
/* dev on the port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
dev = device;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
printf("dev%d is not present on port#%d\n", dev, num);
return 0;
}
/* Select device */
dev_select(&port[num].ioaddr, dev);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", 0);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
sata_outb(0, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
sata_outb(1, port[num].ioaddr.nsect_addr);
sata_outb(((blknr) >> 0) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_READ_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_READ,
port[num].ioaddr.command_addr);
}
mdelay(50);
/* may take up to 4 sec */
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
u8 err = 0;
printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
err = sata_inb(port[num].ioaddr.error_addr);
printf("Error reg = 0x%x\n", err);
return n;
}
input_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(50);
++n;
++blknr;
buffer += ATA_SECTORWORDS;
}
return n;
}
ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
unsigned char status = 0, num = 0, dev = 0, mask = 0;
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
/* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
/* dev on the Port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
dev = device;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
/* Select device */
dev_select(&port[num].ioaddr, dev);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n",
port[num].port_no);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
sata_outb(0, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
sata_outb(1, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_WRITE_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_WRITE,
port[num].ioaddr.command_addr);
}
mdelay(50);
/* may take up to 4 sec */
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
return n;
}
output_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(50);
++n;
++blknr;
buffer += ATA_SECTORWORDS;
}
return n;
}
int scan_sata(int dev)
{
return 0;
}

View file

@ -1,71 +0,0 @@
#ifndef __ATA_PIIX_H__
#define __ATA_PIIX_H__
struct sata_ioports {
unsigned long cmd_addr;
unsigned long data_addr;
unsigned long error_addr;
unsigned long feature_addr;
unsigned long nsect_addr;
unsigned long lbal_addr;
unsigned long lbam_addr;
unsigned long lbah_addr;
unsigned long device_addr;
unsigned long status_addr;
unsigned long command_addr;
unsigned long altstatus_addr;
unsigned long ctl_addr;
unsigned long bmdma_addr;
unsigned long scr_addr;
};
struct sata_port {
unsigned char port_no; /* primary=0, secondary=1 */
struct sata_ioports ioaddr; /* ATA cmd/ctl/dma reg blks */
unsigned char ctl_reg;
unsigned char last_ctl;
unsigned char port_state; /* 1-port is available and */
/* 0-port is not available */
unsigned char dev_mask;
};
/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/
#ifdef SATA_DECL /* SATA library specific declarations */
inline void ata_dump_id(u16 *id)
{
debug("49 = 0x%04x "
"53 = 0x%04x "
"63 = 0x%04x "
"64 = 0x%04x "
"75 = 0x%04x\n", id[49], id[53], id[63], id[64], id[75]);
debug("80 = 0x%04x "
"81 = 0x%04x "
"82 = 0x%04x "
"83 = 0x%04x "
"84 = 0x%04x\n", id[80], id[81], id[82], id[83], id[84]);
debug("88 = 0x%04x " "93 = 0x%04x\n", id[88], id[93]);
}
#endif
#ifdef SATA_DECL /*SATA library specific declarations */
int sata_bus_softreset(int num);
void sata_identify(int num, int dev);
void sata_port(struct sata_ioports *ioport);
void set_Feature_cmd(int num, int dev);
int sata_devchk(struct sata_ioports *ioaddr, int dev);
void dev_select(struct sata_ioports *ioaddr, int dev);
u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max);
u8 sata_chk_status(struct sata_ioports *ioaddr);
#endif
/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/
#ifdef DRV_DECL /* Driver specific declaration */
int init_sata(int dev);
#endif
#ifdef DRV_DECL /* Defines Driver Specific variables */
struct sata_port port[CONFIG_SYS_SATA_MAXBUS];
#endif
#endif /* __ATA_PIIX_H__ */

View file

@ -8,9 +8,12 @@
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <dm/lists.h>
#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
int cpu_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_ops *ops = cpu_get_ops(dev);
@ -25,12 +28,22 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_desc)
if (!ops->get_info)
return -ENOSYS;
return ops->get_info(dev, info);
}
int cpu_get_count(struct udevice *dev)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_count)
return -ENOSYS;
return ops->get_count(dev);
}
U_BOOT_DRIVER(cpu_bus) = {
.name = "cpu_bus",
.id = UCLASS_SIMPLE_BUS,

View file

@ -296,6 +296,7 @@ int pci_auto_config_devices(struct udevice *bus)
!ret && dev;
ret = device_find_next_child(&dev)) {
struct pci_child_platdata *pplat;
struct pci_controller *ctlr_hose;
pplat = dev_get_parent_platdata(dev);
unsigned int max_bus;
@ -303,7 +304,10 @@ int pci_auto_config_devices(struct udevice *bus)
bdf = PCI_ADD_BUS(bus->seq, pplat->devfn);
debug("%s: device %s\n", __func__, dev->name);
max_bus = pciauto_config_device(hose, bdf);
/* The root controller has the region information */
ctlr_hose = hose->ctlr->uclass_priv;
max_bus = pciauto_config_device(ctlr_hose, bdf);
sub_bus = max(sub_bus, max_bus);
}
debug("%s: done\n", __func__);
@ -330,7 +334,7 @@ int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf)
sub_bus = pci_get_bus_max() + 1;
debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
pciauto_prescan_setup_bridge(hose, bdf, bus->seq);
pciauto_prescan_setup_bridge(hose, bdf, sub_bus);
ret = device_probe(bus);
if (ret) {
@ -440,6 +444,7 @@ static int decode_regions(struct pci_controller *hose, const void *blob,
{
int pci_addr_cells, addr_cells, size_cells;
int cells_per_record;
phys_addr_t addr;
const u32 *prop;
int len;
int i;
@ -490,8 +495,11 @@ static int decode_regions(struct pci_controller *hose, const void *blob,
}
/* Add a region for our local memory */
pci_set_region(hose->regions + hose->region_count++, 0, 0,
gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
addr = gd->ram_size;
if (gd->pci_ram_top && gd->pci_ram_top < addr)
addr = gd->pci_ram_top;
pci_set_region(hose->regions + hose->region_count++, 0, 0, addr,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
return 0;
}

View file

@ -87,6 +87,8 @@ void pciauto_setup_device(struct pci_controller *hose,
pci_size_t bar_size;
u16 cmdstat = 0;
int bar, bar_nr = 0;
u8 header_type;
int rom_addr;
#ifndef CONFIG_PCI_ENUM_ONLY
pci_addr_t bar_value;
struct pci_region *bar_res;
@ -182,38 +184,32 @@ void pciauto_setup_device(struct pci_controller *hose,
bar_nr++;
}
/* Configure the expansion ROM address */
pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
if (header_type != PCI_HEADER_TYPE_CARDBUS) {
rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
if (bar_response) {
bar_size = -(bar_response & ~1);
DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
if (pciauto_region_allocate(mem, bar_size,
&bar_value) == 0) {
pci_hose_write_config_dword(hose, dev, rom_addr,
bar_value);
}
cmdstat |= PCI_COMMAND_MEMORY;
DEBUGF("\n");
}
}
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
CONFIG_SYS_PCI_CACHE_LINE_SIZE);
pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
}
int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev)
{
pci_addr_t bar_value;
pci_size_t bar_size;
u32 bar_response;
u16 cmdstat = 0;
pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe);
pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response);
if (!bar_response)
return -ENOENT;
bar_size = -(bar_response & ~1);
DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) {
pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS,
bar_value);
}
DEBUGF("\n");
pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
return 0;
}
void pciauto_prescan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus)
{

View file

@ -11,6 +11,7 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <asm/io.h>
@ -221,6 +222,11 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
return phys_addr;
}
#ifdef CONFIG_DM_PCI
/* The root controller has the region information */
hose = hose->ctlr->uclass_priv;
#endif
/*
* if PCI_REGION_MEM is set we do a two pass search with preference
* on matches that don't have PCI_REGION_SYS_MEMORY set

View file

@ -31,6 +31,7 @@
#include <pci_rom.h>
#include <vbe.h>
#include <video_fb.h>
#include <linux/screen_info.h>
#ifdef CONFIG_HAVE_ACPI_RESUME
#include <asm/acpi.h>
@ -79,15 +80,10 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
if (vendev != mapped_vendev)
debug("Device ID mapped to %#08x\n", mapped_vendev);
#ifdef CONFIG_X86_OPTION_ROM_ADDR
rom_address = CONFIG_X86_OPTION_ROM_ADDR;
#ifdef CONFIG_VGA_BIOS_ADDR
rom_address = CONFIG_VGA_BIOS_ADDR;
#else
if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) {
debug("Cannot find option ROM\n");
return -ENOENT;
}
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address);
if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
debug("%s: rom_address=%x\n", __func__, rom_address);
@ -108,6 +104,10 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
printf("Incorrect expansion ROM header signature %04x\n",
le16_to_cpu(rom_header->signature));
#ifndef CONFIG_VGA_BIOS_ADDR
/* Disable expansion ROM address decoding */
pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address);
#endif
return -EINVAL;
}
@ -203,6 +203,7 @@ int vbe_get_video_info(struct graphic_device *gdev)
gdev->gdfBytesPP = vesa->bits_per_pixel / 8;
switch (vesa->bits_per_pixel) {
case 32:
case 24:
gdev->gdfIndex = GDF_32BIT_X888RGB;
break;
@ -229,6 +230,33 @@ int vbe_get_video_info(struct graphic_device *gdev)
#endif
}
void setup_video(struct screen_info *screen_info)
{
#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
struct vesa_mode_info *vesa = &mode_info.vesa;
screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
screen_info->lfb_width = vesa->x_resolution;
screen_info->lfb_height = vesa->y_resolution;
screen_info->lfb_depth = vesa->bits_per_pixel;
screen_info->lfb_linelength = vesa->bytes_per_scanline;
screen_info->lfb_base = vesa->phys_base_ptr;
screen_info->lfb_size =
ALIGN(screen_info->lfb_linelength * screen_info->lfb_height,
65536);
screen_info->lfb_size >>= 16;
screen_info->red_size = vesa->red_mask_size;
screen_info->red_pos = vesa->red_mask_pos;
screen_info->green_size = vesa->green_mask_size;
screen_info->green_pos = vesa->green_mask_pos;
screen_info->blue_size = vesa->blue_mask_size;
screen_info->blue_pos = vesa->blue_mask_pos;
screen_info->rsvd_size = vesa->reserved_mask_size;
screen_info->rsvd_pos = vesa->reserved_mask_pos;
#endif
}
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
{
struct pci_rom_header *rom, *ram;

View file

@ -7,18 +7,21 @@
#include <common.h>
#include <dm.h>
#include <pci.h>
#include <asm/pci.h>
static const struct dm_pci_ops x86_pci_ops = {
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 x86_pci_ids[] = {
{ .compatible = "x86,pci" },
static const struct udevice_id pci_x86_ids[] = {
{ .compatible = "pci-x86" },
{ }
};
U_BOOT_DRIVER(pci_x86) = {
.name = "pci_x86",
.id = UCLASS_PCI,
.of_match = x86_pci_ids,
.ops = &x86_pci_ops,
.of_match = pci_x86_ids,
.ops = &pci_x86_ops,
};

View file

@ -9,10 +9,9 @@
* Date & Time support for the MC146818 (PIXX4) RTC
*/
/*#define DEBUG*/
#include <common.h>
#include <command.h>
#include <dm.h>
#include <rtc.h>
#if defined(__I386__) || defined(CONFIG_MALTA)
@ -24,9 +23,9 @@
#if defined(CONFIG_CMD_DATE)
/* Set this to 1 to clear the CMOS RAM */
#define CLEAR_CMOS 0
#define CLEAR_CMOS 0
#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
#define RTC_SECONDS 0x00
#define RTC_SECONDS_ALARM 0x01
#define RTC_MINUTES 0x02
@ -37,10 +36,10 @@
#define RTC_DATE_OF_MONTH 0x07
#define RTC_MONTH 0x08
#define RTC_YEAR 0x09
#define RTC_CONFIG_A 0x0A
#define RTC_CONFIG_B 0x0B
#define RTC_CONFIG_C 0x0C
#define RTC_CONFIG_D 0x0D
#define RTC_CONFIG_A 0x0a
#define RTC_CONFIG_B 0x0b
#define RTC_CONFIG_C 0x0c
#define RTC_CONFIG_D 0x0d
#define RTC_REG_SIZE 0x80
#define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5)
@ -50,89 +49,7 @@
#define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80
/* ------------------------------------------------------------------------- */
int rtc_get (struct rtc_time *tmp)
{
uchar sec, min, hour, mday, wday, mon, year;
/* here check if rtc can be accessed */
while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80);
sec = rtc_read8(RTC_SECONDS);
min = rtc_read8(RTC_MINUTES);
hour = rtc_read8(RTC_HOURS);
mday = rtc_read8(RTC_DATE_OF_MONTH);
wday = rtc_read8(RTC_DAY_OF_WEEK);
mon = rtc_read8(RTC_MONTH);
year = rtc_read8(RTC_YEAR);
#ifdef RTC_DEBUG
printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
"hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday,
hour, min, sec );
printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
rtc_read8(RTC_CONFIG_D) & 0x3F,
rtc_read8(RTC_HOURS_ALARM),
rtc_read8(RTC_MINUTES_ALARM),
rtc_read8(RTC_SECONDS_ALARM));
#endif
tmp->tm_sec = bcd2bin (sec & 0x7F);
tmp->tm_min = bcd2bin (min & 0x7F);
tmp->tm_hour = bcd2bin (hour & 0x3F);
tmp->tm_mday = bcd2bin (mday & 0x3F);
tmp->tm_mon = bcd2bin (mon & 0x1F);
tmp->tm_year = bcd2bin (year);
tmp->tm_wday = bcd2bin (wday & 0x07);
if(tmp->tm_year<70)
tmp->tm_year+=2000;
else
tmp->tm_year+=1900;
tmp->tm_yday = 0;
tmp->tm_isdst= 0;
#ifdef RTC_DEBUG
printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
return 0;
}
int rtc_set (struct rtc_time *tmp)
{
#ifdef RTC_DEBUG
printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
return 0;
}
void rtc_reset (void)
{
rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */
rtc_write8(RTC_CONFIG_B, 0x00);
rtc_write8(RTC_CONFIG_B, 0x00);
rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
}
/* ------------------------------------------------------------------------- */
/*
* use direct memory access
*/
int rtc_read8(int reg)
static int mc146818_read8(int reg)
{
#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
@ -149,7 +66,7 @@ int rtc_read8(int reg)
#endif
}
void rtc_write8(int reg, uchar val)
static void mc146818_write8(int reg, uchar val)
{
#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
@ -165,6 +82,204 @@ void rtc_write8(int reg, uchar val)
#endif
}
static int mc146818_get(struct rtc_time *tmp)
{
uchar sec, min, hour, mday, wday, mon, year;
/* here check if rtc can be accessed */
while ((mc146818_read8(RTC_CONFIG_A) & 0x80) == 0x80)
;
sec = mc146818_read8(RTC_SECONDS);
min = mc146818_read8(RTC_MINUTES);
hour = mc146818_read8(RTC_HOURS);
mday = mc146818_read8(RTC_DATE_OF_MONTH);
wday = mc146818_read8(RTC_DAY_OF_WEEK);
mon = mc146818_read8(RTC_MONTH);
year = mc146818_read8(RTC_YEAR);
#ifdef RTC_DEBUG
printf("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday, hour, min, sec);
printf("Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
mc146818_read8(RTC_CONFIG_D) & 0x3f,
mc146818_read8(RTC_HOURS_ALARM),
mc146818_read8(RTC_MINUTES_ALARM),
mc146818_read8(RTC_SECONDS_ALARM));
#endif
tmp->tm_sec = bcd2bin(sec & 0x7f);
tmp->tm_min = bcd2bin(min & 0x7f);
tmp->tm_hour = bcd2bin(hour & 0x3f);
tmp->tm_mday = bcd2bin(mday & 0x3f);
tmp->tm_mon = bcd2bin(mon & 0x1f);
tmp->tm_year = bcd2bin(year);
tmp->tm_wday = bcd2bin(wday & 0x07);
if (tmp->tm_year < 70)
tmp->tm_year += 2000;
else
tmp->tm_year += 1900;
tmp->tm_yday = 0;
tmp->tm_isdst = 0;
#ifdef RTC_DEBUG
printf("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
return 0;
}
static int mc146818_set(struct rtc_time *tmp)
{
#ifdef RTC_DEBUG
printf("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
/* Disable the RTC to update the regs */
mc146818_write8(RTC_CONFIG_B, 0x82);
mc146818_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
mc146818_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
mc146818_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
mc146818_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
mc146818_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
mc146818_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
/* Enable the RTC to update the regs */
mc146818_write8(RTC_CONFIG_B, 0x02);
return 0;
}
static void mc146818_reset(void)
{
/* Disable the RTC to update the regs */
mc146818_write8(RTC_CONFIG_B, 0x82);
/* Normal OP */
mc146818_write8(RTC_CONFIG_A, 0x20);
mc146818_write8(RTC_CONFIG_B, 0x00);
mc146818_write8(RTC_CONFIG_B, 0x00);
/* Enable the RTC to update the regs */
mc146818_write8(RTC_CONFIG_B, 0x02);
}
static void mc146818_init(void)
{
#if CLEAR_CMOS
int i;
rtc_write8(RTC_SECONDS_ALARM, 0);
rtc_write8(RTC_MINUTES_ALARM, 0);
rtc_write8(RTC_HOURS_ALARM, 0);
for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
rtc_write8(i, 0);
printf("RTC: zeroing CMOS RAM\n");
#endif
/* Setup the real time clock */
mc146818_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
/* Setup the frequency it operates at */
mc146818_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
RTC_CONFIG_A_RATE_1024HZ);
/* Ensure all reserved bits are 0 in register D */
mc146818_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
/* Clear any pending interrupts */
mc146818_read8(RTC_CONFIG_C);
}
#endif
#ifdef CONFIG_DM_RTC
static int rtc_mc146818_get(struct udevice *dev, struct rtc_time *time)
{
return mc146818_get(time);
}
static int rtc_mc146818_set(struct udevice *dev, const struct rtc_time *time)
{
return mc146818_set((struct rtc_time *)time);
}
static int rtc_mc146818_reset(struct udevice *dev)
{
mc146818_reset();
return 0;
}
static int rtc_mc146818_read8(struct udevice *dev, unsigned int reg)
{
return mc146818_read8(reg);
}
static int rtc_mc146818_write8(struct udevice *dev, unsigned int reg, int val)
{
mc146818_write8(reg, val);
return 0;
}
static int rtc_mc146818_bind(struct udevice *dev)
{
mc146818_init();
return 0;
}
static const struct rtc_ops rtc_mc146818_ops = {
.get = rtc_mc146818_get,
.set = rtc_mc146818_set,
.reset = rtc_mc146818_reset,
.read8 = rtc_mc146818_read8,
.write8 = rtc_mc146818_write8,
};
static const struct udevice_id rtc_mc146818_ids[] = {
{ .compatible = "motorola,mc146818" },
{ }
};
U_BOOT_DRIVER(rtc_mc146818) = {
.name = "rtc_mc146818",
.id = UCLASS_RTC,
.of_match = rtc_mc146818_ids,
.bind = rtc_mc146818_bind,
.ops = &rtc_mc146818_ops,
};
#else /* !CONFIG_DM_RTC */
int rtc_get(struct rtc_time *tmp)
{
return mc146818_get(tmp);
}
int rtc_set(struct rtc_time *tmp)
{
return mc146818_set(tmp);
}
void rtc_reset(void)
{
mc146818_reset();
}
int rtc_read8(int reg)
{
return mc146818_read8(reg);
}
void rtc_write8(int reg, uchar val)
{
mc146818_write8(reg, val);
}
u32 rtc_read32(int reg)
{
u32 value = 0;
@ -186,26 +301,7 @@ void rtc_write32(int reg, u32 value)
void rtc_init(void)
{
#if CLEAR_CMOS
int i;
rtc_write8(RTC_SECONDS_ALARM, 0);
rtc_write8(RTC_MINUTES_ALARM, 0);
rtc_write8(RTC_HOURS_ALARM, 0);
for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
rtc_write8(i, 0);
printf("RTC: zeroing CMOS RAM\n");
#endif
/* Setup the real time clock */
rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
/* Setup the frequency it operates at */
rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
RTC_CONFIG_A_RATE_1024HZ);
/* Ensure all reserved bits are 0 in register D */
rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
/* Clear any pending interrupts */
rtc_read8(RTC_CONFIG_C);
mc146818_init();
}
#endif
#endif /* CONFIG_DM_RTC */

View file

@ -40,6 +40,7 @@ struct ich_spi_priv {
int status;
int control;
int bbar;
int bcr;
uint32_t *pr; /* only for ich9 */
int speed; /* pointer to speed control */
ulong max_speed; /* Maximum bus speed in MHz */
@ -239,6 +240,7 @@ static int ich_init_controller(struct ich_spi_platdata *plat,
ctlr->speed = ctlr->control + 2;
ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
ctlr->preop = offsetof(struct ich9_spi_regs, preop);
ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
ctlr->pr = &ich9_spi->pr[0];
ctlr->base = ich9_spi;
} else {
@ -411,6 +413,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
struct udevice *bus = dev_get_parent(dev);
struct ich_spi_platdata *plat = dev_get_platdata(bus);
struct ich_spi_priv *ctlr = dev_get_priv(bus);
uint16_t control;
int16_t opcode_index;
@ -422,7 +425,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
int using_cmd = 0;
int ret;
/* Ee don't support writing partial bytes. */
/* We don't support writing partial bytes */
if (bitlen % 8) {
debug("ICH SPI: Accessing partial bytes not supported\n");
return -EPROTONOSUPPORT;
@ -477,7 +480,10 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (ret < 0)
return ret;
ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
if (plat->ich_version == 7)
ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
else
ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
spi_setup_type(trans, using_cmd ? bytes : 0);
opcode_index = spi_setup_opcode(ctlr, trans);
@ -601,7 +607,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
return status;
if (status & SPIS_FCERR) {
debug("ICH SPI: Data transaction error\n");
debug("ICH SPI: Data transaction error %x\n", status);
return -EIO;
}
@ -619,7 +625,6 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
return 0;
}
/*
* This uses the SPI controller from the Intel Cougar Point and Panther Point
* PCH to write-protect portions of the SPI flash until reboot. The changes
@ -685,13 +690,10 @@ static int ich_spi_probe(struct udevice *bus)
* v9, deassert SMM BIOS Write Protect Disable.
*/
if (plat->use_sbase) {
struct ich9_spi_regs *ich9_spi;
ich9_spi = priv->base;
bios_cntl = ich_readb(priv, ich9_spi->bcr);
bios_cntl = ich_readb(priv, priv->bcr);
bios_cntl &= ~(1 << 5); /* clear Enable InSMM_STS (EISS) */
bios_cntl |= 1; /* Write Protect Disable (WPD) */
ich_writeb(priv, bios_cntl, ich9_spi->bcr);
ich_writeb(priv, bios_cntl, priv->bcr);
} else {
pci_read_config_byte(plat->dev, 0xdc, &bios_cntl);
if (plat->ich_version == 9)

View file

@ -1,6 +1,5 @@
/*
*
* Vesa frame buffer driver for x86
* VESA frame buffer driver
*
* Copyright (C) 2014 Google, Inc
*
@ -17,16 +16,6 @@
*/
GraphicDevice ctfb;
/* Devices to allow - only the last one works fully */
struct pci_device_id vesa_video_ids[] = {
{ .vendor = 0x102b, .device = 0x0525 },
{ .vendor = 0x1002, .device = 0x5159 },
{ .vendor = 0x1002, .device = 0x4752 },
{ .vendor = 0x1002, .device = 0x5452 },
{ .vendor = 0x8086, .device = 0x0f31 },
{},
};
void *video_hw_init(void)
{
GraphicDevice *gdev = &ctfb;
@ -36,8 +25,7 @@ void *video_hw_init(void)
printf("Video: ");
if (vbe_get_video_info(gdev)) {
/* TODO: Should we look these up by class? */
dev = pci_find_devices(vesa_video_ids, 0);
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
if (dev == -1) {
printf("no card detected\n");
return NULL;

View file

@ -93,6 +93,7 @@ typedef struct global_data {
#endif
#ifdef CONFIG_PCI
struct pci_controller *hose; /* PCI hose for early use */
phys_addr_t pci_ram_top; /* top of region accessible to PCI */
#endif
#ifdef CONFIG_PCI_BOOTDELAY
int pcidelay_done;

View file

@ -32,15 +32,16 @@
#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_PCI_CONFIG_HOST_BRIDGE
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
#define CONFIG_E1000
#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial\0" \
"stdout=serial\0" \
"stderr=serial\0"
#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,vga,usbkbd\0" \
"stdout=serial,vga\0" \
"stderr=serial,vga\0"
#define CONFIG_SCSI_DEV_LIST \
#define CONFIG_SCSI_DEV_LIST \
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SATA}
#define CONFIG_SPI_FLASH_SST
@ -55,9 +56,8 @@
#define CONFIG_PCH_GBE
#define CONFIG_PHYLIB
/* Video is not supported */
#undef CONFIG_VIDEO
#undef CONFIG_CFB_CONSOLE
/* TunnelCreek IGD support */
#define CONFIG_VGA_AS_SINGLE_DEVICE
/* Environment configuration */
#define CONFIG_ENV_SECT_SIZE 0x1000

View file

@ -32,6 +32,7 @@
#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_PCI_CONFIG_HOST_BRIDGE
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
#define CONFIG_RTL8169
@ -52,9 +53,6 @@
#undef CONFIG_USB_MAX_CONTROLLER_COUNT
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
#define CONFIG_X86_OPTION_ROM_FILE vga.bin
#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000
#define VIDEO_IO_OFFSET 0
#define CONFIG_X86EMU_RAW_IO
#define CONFIG_VGA_AS_SINGLE_DEVICE
@ -65,8 +63,7 @@
/* Avoid a warning in the Realtek Ethernet driver */
#define CONFIG_SYS_CACHELINE_SIZE 16
/* Environment in SPI flash is unsupported for now */
#undef CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_IS_NOWHERE
#define CONFIG_ENV_SECT_SIZE 0x1000
#define CONFIG_ENV_OFFSET 0x007fe000
#endif /* __CONFIG_H */

View file

@ -26,9 +26,6 @@
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}, \
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_AHCI}
#define CONFIG_X86_OPTION_ROM_FILE pci8086,0166.bin
#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000
#define CONFIG_PCI_MEM_BUS 0xe0000000
#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
#define CONFIG_PCI_MEM_SIZE 0x10000000

View file

@ -58,6 +58,14 @@ struct cpu_ops {
* @return 0 if OK, -ve on error
*/
int (*get_info)(struct udevice *dev, struct cpu_info *info);
/**
* get_count() - Get number of CPUs
*
* @dev: Device to check (UCLASS_CPU)
* @return CPU count if OK, -ve on error
*/
int (*get_count)(struct udevice *dev);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops)
@ -81,4 +89,12 @@ int cpu_get_desc(struct udevice *dev, char *buf, int size);
*/
int cpu_get_info(struct udevice *dev, struct cpu_info *info);
/**
* cpu_get_count() - Get number of CPUs
*
* @dev: Device to check (UCLASS_CPU)
* @return CPU count if OK, -ve on error
*/
int cpu_get_count(struct udevice *dev);
#endif

View file

@ -513,6 +513,16 @@ struct pci_controller {
int indirect_type;
/*
* TODO(sjg@chromium.org): With driver model we use struct
* pci_controller for both the controller and any bridge devices
* attached to it. But there is only one region list and it is in the
* top-level controller.
*
* This could be changed so that struct pci_controller is only used
* for PCI controllers and a separate UCLASS (or perhaps
* UCLASS_PCI_GENERIC) is used for bridges.
*/
struct pci_region regions[MAX_PCI_REGIONS];
int region_count;
@ -711,15 +721,6 @@ void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
* */
u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
/**
* pciauto_setup_rom() - Set up access to a device ROM
*
* @hose: PCI hose to use
* @dev: PCI device to adjust
* @return 0 if done, -ve on error
*/
int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev);
/**
* pci_hose_find_devices() - Find devices by vendor/device ID
*

View file

@ -12,7 +12,7 @@
#define _VBE_H
/* these structs are for input from and output to OF */
struct __packed screen_info {
struct __packed vbe_screen_info {
u8 display_type; /* 0=NONE, 1= analog, 2=digital */
u16 screen_width;
u16 screen_height;
@ -23,7 +23,7 @@ struct __packed screen_info {
u8 edid_block_zero[128];
};
struct __packed screen_info_input {
struct __packed vbe_screen_info_input {
u8 signature[4];
u16 size_reserved;
u8 monitor_number;

View file

@ -356,7 +356,7 @@ class BuilderThread(threading.Thread):
# Now write the actual build output
if keep_outputs:
self.CopyFiles(result.out_dir, build_dir, '', ['u-boot*', '*.bin',
'*.map', '*.img', 'MLO', 'include/autoconf.mk',
'*.map', '*.img', 'MLO', 'SPL', 'include/autoconf.mk',
'spl/u-boot-spl*'])
def CopyFiles(self, out_dir, build_dir, dirname, patterns):

View file

@ -987,7 +987,7 @@ int main(int argc, char *argv[])
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
ifile->addr = strtol(optarg, NULL, 0);
ifile->addr = strtoll(optarg, NULL, 0);
ifile->type = opt == 'f' ? IF_fdt :
opt == 'U' ? IF_uboot : IF_normal;
if (ifile->type == IF_fdt)