mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Merge git://git.denx.de/u-boot-x86
This commit is contained in:
commit
605e15db2b
77 changed files with 2065 additions and 1616 deletions
4
Makefile
4
Makefile
|
@ -1035,8 +1035,8 @@ ifneq ($(CONFIG_HAVE_CMC),)
|
|||
IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE)
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),)
|
||||
IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILE)
|
||||
ifneq ($(CONFIG_HAVE_VGA_BIOS),)
|
||||
IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE)
|
||||
endif
|
||||
|
||||
quiet_cmd_ifdtool = IFDTOOL $@
|
||||
|
|
|
@ -69,6 +69,21 @@ config X86_RESET_VECTOR
|
|||
bool
|
||||
default n
|
||||
|
||||
config RESET_SEG_START
|
||||
hex
|
||||
depends on X86_RESET_VECTOR
|
||||
default 0xffff0000
|
||||
|
||||
config RESET_SEG_SIZE
|
||||
hex
|
||||
depends on X86_RESET_VECTOR
|
||||
default 0x10000
|
||||
|
||||
config RESET_VEC_LOC
|
||||
hex
|
||||
depends on X86_RESET_VECTOR
|
||||
default 0xfffffff0
|
||||
|
||||
config SYS_X86_START16
|
||||
hex
|
||||
depends on X86_RESET_VECTOR
|
||||
|
@ -173,14 +188,6 @@ config X86_RAMTEST
|
|||
to work correctly. It is not exhaustive but can save time by
|
||||
detecting obvious failures.
|
||||
|
||||
config MARK_GRAPHICS_MEM_WRCOMB
|
||||
bool "Mark graphics memory as write-combining"
|
||||
default n
|
||||
help
|
||||
The graphics performance may increase if the graphics
|
||||
memory is set as write-combining cache type. This option
|
||||
enables marking the graphics memory as write-combining.
|
||||
|
||||
config HAVE_FSP
|
||||
bool "Add an Firmware Support Package binary"
|
||||
help
|
||||
|
@ -220,17 +227,6 @@ config FSP_TEMP_RAM_ADDR
|
|||
Stack top address which is used in FspInit after DRAM is ready and
|
||||
CAR is disabled.
|
||||
|
||||
config MAX_CPUS
|
||||
int "Maximum number of CPUs permitted"
|
||||
default 4
|
||||
help
|
||||
When using multi-CPU chips it is possible for U-Boot to start up
|
||||
more than one CPU. The stack memory used by all of these CPUs is
|
||||
pre-allocated so at present U-Boot wants to know the maximum
|
||||
number of CPUs that may be present. Set this to at least as high
|
||||
as the number of CPUs in your system (it uses about 4KB of RAM for
|
||||
each CPU).
|
||||
|
||||
config SMP
|
||||
bool "Enable Symmetric Multiprocessing"
|
||||
default n
|
||||
|
@ -241,8 +237,21 @@ config SMP
|
|||
only one CPU will be enabled regardless of the number of CPUs
|
||||
available.
|
||||
|
||||
config MAX_CPUS
|
||||
int "Maximum number of CPUs permitted"
|
||||
depends on SMP
|
||||
default 4
|
||||
help
|
||||
When using multi-CPU chips it is possible for U-Boot to start up
|
||||
more than one CPU. The stack memory used by all of these CPUs is
|
||||
pre-allocated so at present U-Boot wants to know the maximum
|
||||
number of CPUs that may be present. Set this to at least as high
|
||||
as the number of CPUs in your system (it uses about 4KB of RAM for
|
||||
each CPU).
|
||||
|
||||
config AP_STACK_SIZE
|
||||
hex
|
||||
depends on SMP
|
||||
default 0x1000
|
||||
help
|
||||
Each additional CPU started by U-Boot requires its own stack. This
|
||||
|
@ -270,6 +279,28 @@ config TSC_FREQ_IN_MHZ
|
|||
help
|
||||
The running frequency in MHz of Time-Stamp Counter (TSC).
|
||||
|
||||
config HAVE_VGA_BIOS
|
||||
bool "Add a VGA BIOS image"
|
||||
help
|
||||
Select this option if you have a VGA BIOS image that you would
|
||||
like to add to your ROM.
|
||||
|
||||
config VGA_BIOS_FILE
|
||||
string "VGA BIOS image filename"
|
||||
depends on HAVE_VGA_BIOS
|
||||
default "vga.bin"
|
||||
help
|
||||
The filename of the VGA BIOS image in the board directory.
|
||||
|
||||
config VGA_BIOS_ADDR
|
||||
hex "VGA BIOS image location"
|
||||
depends on HAVE_VGA_BIOS
|
||||
default 0xfff90000
|
||||
help
|
||||
The location of VGA BIOS image in the SPI flash. For example, base
|
||||
address of 0xfff90000 indicates that the image will be put at offset
|
||||
0x90000 from the beginning of a 1MB flash device.
|
||||
|
||||
menu "System tables"
|
||||
|
||||
config GENERATE_PIRQ_TABLE
|
||||
|
@ -296,6 +327,15 @@ config GENERATE_SFI_TABLE
|
|||
|
||||
For more information, see http://simplefirmware.org
|
||||
|
||||
config GENERATE_MP_TABLE
|
||||
bool "Generate an MP (Multi-Processor) table"
|
||||
default n
|
||||
help
|
||||
Generate an MP (Multi-Processor) table for this board. The MP table
|
||||
provides a way for the operating system to support for symmetric
|
||||
multiprocessing as well as symmetric I/O interrupt handling with
|
||||
the local APIC and I/O APIC.
|
||||
|
||||
endmenu
|
||||
|
||||
config MAX_PIRQ_LINKS
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
extra-y = start.o
|
||||
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
|
||||
obj-y += interrupts.o cpu.o call64.o
|
||||
obj-y += interrupts.o cpu.o cpu_x86.o call64.o
|
||||
|
||||
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
|
||||
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
|
||||
|
@ -19,7 +19,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
|
|||
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
|
||||
obj-$(CONFIG_INTEL_QUARK) += quark/
|
||||
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
|
||||
obj-y += irq.o lapic.o
|
||||
obj-y += irq.o lapic.o ioapic.o
|
||||
obj-$(CONFIG_SMP) += mp_init.o
|
||||
obj-y += mtrr.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
|
|
@ -7,5 +7,4 @@
|
|||
obj-y += cpu.o
|
||||
obj-y += early_uart.o
|
||||
obj-y += fsp_configs.o
|
||||
obj-y += pci.o
|
||||
obj-y += valleyview.o
|
||||
|
|
|
@ -10,79 +10,11 @@
|
|||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu_x86.h>
|
||||
#include <asm/lapic.h>
|
||||
#include <asm/mp.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/turbo.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static int enable_smis(struct udevice *cpu, void *unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mp_flight_record mp_steps[] = {
|
||||
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
|
||||
/* Wait for APs to finish initialization before proceeding. */
|
||||
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
|
||||
};
|
||||
|
||||
static int detect_num_cpus(void)
|
||||
{
|
||||
int ecx = 0;
|
||||
|
||||
/*
|
||||
* Use the algorithm described in Intel 64 and IA-32 Architectures
|
||||
* Software Developer's Manual Volume 3 (3A, 3B & 3C): System
|
||||
* Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
|
||||
* of CPUID Extended Topology Leaf.
|
||||
*/
|
||||
while (1) {
|
||||
struct cpuid_result leaf_b;
|
||||
|
||||
leaf_b = cpuid_ext(0xb, ecx);
|
||||
|
||||
/*
|
||||
* Bay Trail doesn't have hyperthreading so just determine the
|
||||
* number of cores by from level type (ecx[15:8] == * 2)
|
||||
*/
|
||||
if ((leaf_b.ecx & 0xff00) == 0x0200)
|
||||
return leaf_b.ebx & 0xffff;
|
||||
ecx++;
|
||||
}
|
||||
}
|
||||
|
||||
static int baytrail_init_cpus(void)
|
||||
{
|
||||
struct mp_params mp_params;
|
||||
|
||||
lapic_setup();
|
||||
|
||||
mp_params.num_cpus = detect_num_cpus();
|
||||
mp_params.parallel_microcode_load = 0,
|
||||
mp_params.flight_plan = &mp_steps[0];
|
||||
mp_params.num_records = ARRAY_SIZE(mp_steps);
|
||||
mp_params.microcode_pointer = 0;
|
||||
|
||||
if (mp_init(&mp_params)) {
|
||||
printf("Warning: MP init failure\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int x86_init_cpus(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
debug("Init additional CPUs\n");
|
||||
baytrail_init_cpus();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_max_freq(void)
|
||||
{
|
||||
msr_t perf_ctl;
|
||||
|
@ -175,19 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_x86_baytrail_bind(struct udevice *dev)
|
||||
static int baytrail_get_count(struct udevice *dev)
|
||||
{
|
||||
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||
int ecx = 0;
|
||||
|
||||
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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -10,8 +10,8 @@ CROSS_COMPILE ?= i386-linux-
|
|||
PLATFORM_CPPFLAGS += -D__I386__
|
||||
|
||||
# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
|
||||
LDPPFLAGS += -DRESET_SEG_START=0xffff0000
|
||||
LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
|
||||
LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
|
||||
LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
|
||||
LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE)
|
||||
LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
|
||||
LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
|
||||
LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)"
|
||||
|
|
|
@ -11,29 +11,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pci.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static const struct dm_pci_ops pci_x86_ops = {
|
||||
.read_config = pci_x86_read_config,
|
||||
.write_config = pci_x86_write_config,
|
||||
};
|
||||
|
||||
static const struct udevice_id pci_x86_ids[] = {
|
||||
{ .compatible = "pci-x86" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pci_x86_drv) = {
|
||||
.name = "pci_x86",
|
||||
.id = UCLASS_PCI,
|
||||
.of_match = pci_x86_ids,
|
||||
.ops = &pci_x86_ops,
|
||||
};
|
||||
|
||||
static const struct udevice_id generic_pch_ids[] = {
|
||||
{ .compatible = "intel,pch" },
|
||||
|
|
|
@ -21,12 +21,15 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/control_regs.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/lapic.h>
|
||||
#include <asm/mp.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/processor-flags.h>
|
||||
|
@ -164,6 +167,26 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
|
|||
load_fs(X86_GDT_ENTRY_32BIT_FS);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_FSP
|
||||
/*
|
||||
* Setup FSP execution environment GDT
|
||||
*
|
||||
* Per Intel FSP external architecture specification, before calling any FSP
|
||||
* APIs, we need make sure the system is in flat 32-bit mode and both the code
|
||||
* and data selectors should have full 4GB access range. Here we reuse the one
|
||||
* we used in arch/x86/cpu/start16.S, and reload the segement registers.
|
||||
*/
|
||||
void setup_fsp_gdt(void)
|
||||
{
|
||||
load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
|
||||
load_ds(X86_GDT_ENTRY_32BIT_DS);
|
||||
load_ss(X86_GDT_ENTRY_32BIT_DS);
|
||||
load_es(X86_GDT_ENTRY_32BIT_DS);
|
||||
load_fs(X86_GDT_ENTRY_32BIT_DS);
|
||||
load_gs(X86_GDT_ENTRY_32BIT_DS);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __weak x86_cleanup_before_linux(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTSTAGE_STASH
|
||||
|
@ -330,6 +353,28 @@ int x86_cpu_init_f(void)
|
|||
|
||||
gd->arch.has_mtrr = has_mtrr();
|
||||
}
|
||||
/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
|
||||
gd->pci_ram_top = 0x80000000U;
|
||||
|
||||
/* Configure fixed range MTRRs for some legacy regions */
|
||||
if (gd->arch.has_mtrr) {
|
||||
u64 mtrr_cap;
|
||||
|
||||
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
|
||||
if (mtrr_cap & MTRR_CAP_FIX) {
|
||||
/* Mark the VGA RAM area as uncacheable */
|
||||
native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0);
|
||||
|
||||
/* Mark the PCI ROM area as uncacheable */
|
||||
native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0);
|
||||
native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0);
|
||||
native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0);
|
||||
native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0);
|
||||
|
||||
/* Enable the fixed range MTRRs */
|
||||
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -520,16 +565,6 @@ char *cpu_get_name(char *name)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
if (size < CPU_MAX_NAME_LEN)
|
||||
return -ENOSPC;
|
||||
|
||||
cpu_get_name(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int default_print_cpuinfo(void)
|
||||
{
|
||||
printf("CPU: %s, vendor %s, device %xh\n",
|
||||
|
@ -613,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
76
arch/x86/cpu/cpu_x86.c
Normal 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
21
arch/x86/cpu/ioapic.c
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ...
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
6
arch/x86/dts/rtc.dtsi
Normal file
|
@ -0,0 +1,6 @@
|
|||
/ {
|
||||
rtc {
|
||||
compatible = "motorola,mc146818";
|
||||
reg = <0x70 2>;
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
|
34
arch/x86/include/asm/cpu_x86.h
Normal file
34
arch/x86/include/asm/cpu_x86.h
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
444
arch/x86/include/asm/mpspec.h
Normal file
444
arch/x86/include/asm/mpspec.h
Normal 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 */
|
|
@ -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__)
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
382
arch/x86/lib/mpspec.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue