Merge branch 'master' of git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2015-02-10 10:42:56 -05:00
commit db7a7dee68
102 changed files with 11497 additions and 272 deletions

View File

@ -729,8 +729,9 @@ ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
endif
ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
# We can't do this yet due to the need for binary blobs
# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
ifneq ($(BUILD_ROM),)
ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
endif
# enable combined SPL/u-boot/dtb rules for tegra
ifneq ($(CONFIG_TEGRA),)

View File

@ -41,6 +41,30 @@ config TARGET_CROWNBAY
Intel Platform Controller Hub EG20T, other system components and
peripheral connectors for PCIe/SATA/USB/LAN/SD/UART/Audio/LVDS.
config TARGET_MINNOWMAX
bool "Support Intel Minnowboard MAX"
help
This is the Intel Minnowboard MAX. It contains an Atom E3800
processor in a small form factor with Ethernet, micro-SD, USB 2,
USB 3, SATA, serial console, some GPIOs and HDMI 1.3 video out.
It requires some binary blobs - see README.x86 for details.
Note that PCIE_ECAM_BASE is set up by the FSP so the value used
by U-Boot matches that value.
config TARGET_GALILEO
bool "Support Intel Galileo"
help
This is the Intel Galileo board, which is the first in a family of
Arduino-certified development and prototyping boards based on Intel
architecture. It includes an Intel Quark SoC X1000 processor, a 32-bit
single-core, single-thread, Intel Pentium processor instrunction set
architecture (ISA) compatible, operating at speeds up to 400Mhz,
along with 256MB DDR3 memory. It supports a wide range of industry
standard I/O interfaces, including a full-sized mini-PCIe slot,
one 100Mb Ethernet port, a microSD card slot, a USB host port and
a USB client port.
endchoice
config RAMBASE
@ -324,6 +348,54 @@ config FRAMEBUFFER_VESA_MODE
endmenu
config HAVE_FSP
bool "Add an Firmware Support Package binary"
help
Select this option to add an Firmware Support Package binary to
the resulting U-Boot image. It is a binary blob which U-Boot uses
to set up SDRAM and other chipset specific initialization.
Note: Without this binary U-Boot will not be able to set up its
SDRAM so will not boot.
config FSP_FILE
string "Firmware Support Package binary filename"
depends on HAVE_FSP
default "fsp.bin"
help
The filename of the file to use as Firmware Support Package binary
in the board directory.
config FSP_ADDR
hex "Firmware Support Package binary location"
depends on HAVE_FSP
default 0xfffc0000
help
FSP is not Position Independent Code (PIC) and the whole FSP has to
be rebased if it is placed at a location which is different from the
perferred base address specified during the FSP build. Use Intel's
Binary Configuration Tool (BCT) to do the rebase.
The default base address of 0xfffc0000 indicates that the binary must
be located at offset 0xc0000 from the beginning of a 1MB flash device.
config FSP_TEMP_RAM_ADDR
hex
default 0x2000000
help
Stack top address which is used in FspInit after DRAM is ready and
CAR is disabled.
source "arch/x86/cpu/baytrail/Kconfig"
source "arch/x86/cpu/coreboot/Kconfig"
source "arch/x86/cpu/ivybridge/Kconfig"
source "arch/x86/cpu/quark/Kconfig"
source "arch/x86/cpu/queensbay/Kconfig"
config TSC_CALIBRATION_BYPASS
bool "Bypass Time-Stamp Counter (TSC) calibration"
default n
@ -344,16 +416,28 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
source "arch/x86/cpu/coreboot/Kconfig"
source "arch/x86/cpu/ivybridge/Kconfig"
source "arch/x86/cpu/queensbay/Kconfig"
source "board/coreboot/coreboot/Kconfig"
source "board/google/chromebook_link/Kconfig"
source "board/intel/crownbay/Kconfig"
source "board/intel/minnowmax/Kconfig"
source "board/intel/galileo/Kconfig"
config PCIE_ECAM_BASE
hex
default 0xe0000000
help
This is the memory-mapped address of PCI configuration space, which
is only available through the Enhanced Configuration Access
Mechanism (ECAM) with PCI Express. It can be set up almost
anywhere. Before it is set up, it is possible to access PCI
configuration space through I/O access, but memory access is more
convenient. Using this, PCI can be scanned and configured. This
should be set to a region that does not conflict with memory
assigned to PCI devices - i.e. the memory and prefetch regions, as
passed to pci_set_region().
endmenu

View File

@ -12,9 +12,11 @@ extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
obj-y += interrupts.o cpu.o call64.o
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += lapic.o
obj-y += mtrr.o

View File

@ -0,0 +1,9 @@
#
# Copyright (C) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
config INTEL_BAYTRAIL
bool
select HAVE_FSP

View File

@ -0,0 +1,10 @@
#
# Copyright (C) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += early_uart.o
obj-y += fsp_configs.o
obj-y += pci.o
obj-y += valleyview.o

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#define PCI_DEV_CONFIG(segbus, dev, fn) ( \
(((segbus) & 0xfff) << 20) | \
(((dev) & 0x1f) << 15) | \
(((fn) & 0x07) << 12))
/* Platform Controller Unit */
#define LPC_DEV 0x1f
#define LPC_FUNC 0
/* Enable UART */
#define UART_CONT 0x80
/* SCORE Pad definitions */
#define UART_RXD_PAD 82
#define UART_TXD_PAD 83
/* Pad base: PAD_CONF0[n]= PAD_BASE + 16 * n */
#define GPSCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE)
/* IO Memory */
#define IO_BASE_ADDRESS 0xfed0c000
#define IO_BASE_OFFSET_GPSCORE 0x0000
#define IO_BASE_OFFSET_GPNCORE 0x1000
#define IO_BASE_OFFSET_GPSSUS 0x2000
#define IO_BASE_SIZE 0x4000
static inline unsigned int score_pconf0(int pad_num)
{
return GPSCORE_PAD_BASE + pad_num * 16;
}
static void score_select_func(int pad, int func)
{
uint32_t reg;
uint32_t pconf0_addr = score_pconf0(pad);
reg = readl(pconf0_addr);
reg &= ~0x7;
reg |= func & 0x7;
writel(reg, pconf0_addr);
}
static void pci_write_config32(int dev, unsigned int where, u32 value)
{
unsigned long addr;
addr = CONFIG_PCIE_ECAM_BASE | dev | (where & ~3);
writel(value, addr);
}
/* This can be called after memory-mapped PCI is working */
int setup_early_uart(void)
{
/* Enable the legacy UART hardware. */
pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT, 1);
/*
* Set up the pads to the UART function. This allows the signals to
* leave the chip
*/
score_select_func(UART_RXD_PAD, 1);
score_select_func(UART_TXD_PAD, 1);
/* TODO(sjg@chromium.org): Call debug_uart_init() */
return 0;
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: Intel
*/
#include <common.h>
#include <asm/arch/fsp/azalia.h>
#include <asm/fsp/fsp_support.h>
/* ALC262 Verb Table - 10EC0262 */
static const uint32_t verb_table_data13[] = {
/* Pin Complex (NID 0x11) */
0x01171cf0,
0x01171d11,
0x01171e11,
0x01171f41,
/* Pin Complex (NID 0x12) */
0x01271cf0,
0x01271d11,
0x01271e11,
0x01271f41,
/* Pin Complex (NID 0x14) */
0x01471c10,
0x01471d40,
0x01471e01,
0x01471f01,
/* Pin Complex (NID 0x15) */
0x01571cf0,
0x01571d11,
0x01571e11,
0x01571f41,
/* Pin Complex (NID 0x16) */
0x01671cf0,
0x01671d11,
0x01671e11,
0x01671f41,
/* Pin Complex (NID 0x18) */
0x01871c20,
0x01871d98,
0x01871ea1,
0x01871f01,
/* Pin Complex (NID 0x19) */
0x01971c21,
0x01971d98,
0x01971ea1,
0x01971f02,
/* Pin Complex (NID 0x1A) */
0x01a71c2f,
0x01a71d30,
0x01a71e81,
0x01a71f01,
/* Pin Complex */
0x01b71c1f,
0x01b71d40,
0x01b71e21,
0x01b71f02,
/* Pin Complex */
0x01c71cf0,
0x01c71d11,
0x01c71e11,
0x01c71f41,
/* Pin Complex */
0x01d71c01,
0x01d71dc6,
0x01d71e14,
0x01d71f40,
/* Pin Complex */
0x01e71cf0,
0x01e71d11,
0x01e71e11,
0x01e71f41,
/* Pin Complex */
0x01f71cf0,
0x01f71d11,
0x01f71e11,
0x01f71f41,
};
/*
* This needs to be in ROM since if we put it in CAR, FSP init loses it when
* it drops CAR.
*
* TODO(sjg@chromium.org): Move to device tree when FSP allows it
*
* VerbTable: (RealTek ALC262)
* Revision ID = 0xFF, support all steps
* Codec Verb Table For AZALIA
* Codec Address: CAd value (0/1/2)
* Codec Vendor: 0x10EC0262
*/
static const struct pch_azalia_verb_table azalia_verb_table[] = {
{
{
0x10ec0262,
0x0000,
0xff,
0x01,
0x000b,
0x0002,
},
verb_table_data13
}
};
const struct pch_azalia_config azalia_config = {
.pme_enable = 1,
.docking_supported = 1,
.docking_attached = 0,
.hdmi_codec_enable = 1,
.azalia_v_ci_enable = 1,
.rsvdbits = 0,
.azalia_verb_table_num = 1,
.azalia_verb_table = azalia_verb_table,
.reset_wait_timer_us = 300
};
void update_fsp_upd(struct upd_region *fsp_upd)
{
struct memory_down_data *mem;
/*
* Configure everything here to avoid the poor hard-pressed user
* needing to run Intel's binary configuration tool. It may also allow
* us to support the 1GB single core variant easily.
*
* TODO(sjg@chromium.org): Move to device tree
*/
fsp_upd->mrc_init_tseg_size = 8;
fsp_upd->mrc_init_mmio_size = 0x800;
fsp_upd->emmc_boot_mode = 0xff;
fsp_upd->enable_sdio = 1;
fsp_upd->enable_sdcard = 1;
fsp_upd->enable_hsuart0 = 1;
fsp_upd->azalia_config_ptr = (uint32_t)&azalia_config;
fsp_upd->enable_i2_c0 = 0;
fsp_upd->enable_i2_c2 = 0;
fsp_upd->enable_i2_c3 = 0;
fsp_upd->enable_i2_c4 = 0;
fsp_upd->enable_xhci = 0;
fsp_upd->igd_render_standby = 1;
mem = &fsp_upd->memory_params;
mem->enable_memory_down = 1;
mem->dram_speed = 1;
mem->dimm_width = 1;
mem->dimm_density = 2;
mem->dimm_tcl = 0xb;
mem->dimm_trpt_rcd = 0xb;
mem->dimm_twr = 0xc;
mem->dimm_twtr = 6;
mem->dimm_trrd = 6;
mem->dimm_trtp = 6;
mem->dimm_tfaw = 0x14;
}

View File

@ -0,0 +1,46 @@
/*
* 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,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
hose->region_count = 4;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <mmc.h>
#include <pci_ids.h>
#include <asm/post.h>
static struct pci_device_id mmc_supported[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD },
};
int cpu_mmc_init(bd_t *bis)
{
printf("mmc init\n");
return pci_mmc_init("ValleyView SDHCI", mmc_supported,
ARRAY_SIZE(mmc_supported));
}
int arch_cpu_init(void)
{
int ret;
post_code(POST_CPU_INIT);
#ifdef CONFIG_SYS_X86_TSC_TIMER
timer_set_base(rdtsc());
#endif
ret = x86_cpu_init_f();
if (ret)
return ret;
return 0;
}

View File

@ -758,7 +758,8 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
#ifdef CONFIG_VIDEO
start = get_timer(0);
ret = pci_run_vga_bios(dev, int15_handler, false);
ret = pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE |
PCI_ROM_ALLOW_FALLBACK);
debug("BIOS ran in %lums\n", get_timer(start));
#endif
/* Post VBIOS init */

View File

@ -757,7 +757,7 @@ int dram_init(void)
.mchbar = DEFAULT_MCHBAR,
.dmibar = DEFAULT_DMIBAR,
.epbar = DEFAULT_EPBAR,
.pciexbar = CONFIG_MMCONF_BASE_ADDRESS,
.pciexbar = CONFIG_PCIE_ECAM_BASE,
.smbusbar = SMBUS_IO_BASE,
.wdbbar = 0x4000000,
.wdbsize = 0x1000,

126
arch/x86/cpu/quark/Kconfig Normal file
View File

@ -0,0 +1,126 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
config INTEL_QUARK
bool
select HAVE_RMU
select TSC_CALIBRATION_BYPASS
if INTEL_QUARK
config HAVE_RMU
bool "Add a Remote Management Unit (RMU) binary"
help
Select this option to add a Remote Management Unit (RMU) binary
to the resulting U-Boot image. It is a data block (up to 64K) of
machine-specific code which must be put in the flash for the RMU
within the Quark SoC processor to access when powered up before
system BIOS is executed.
config RMU_FILE
string "Remote Management Unit (RMU) binary filename"
depends on HAVE_RMU
default "rmu.bin"
help
The filename of the file to use as Remote Management Unit (RMU)
binary in the board directory.
config RMU_ADDR
hex "Remote Management Unit (RMU) binary location"
depends on HAVE_RMU
default 0xfff00000
help
The location of the RMU binary is determined by a strap. It must be
put in flash at a location matching the strap-determined base address.
The default base address of 0xfff00000 indicates that the binary must
be located at offset 0 from the beginning of a 1MB flash device.
config HAVE_CMC
bool
default HAVE_RMU
config CMC_FILE
string
depends on HAVE_CMC
default RMU_FILE
config CMC_ADDR
hex
depends on HAVE_CMC
default RMU_ADDR
config ESRAM_BASE
hex
default 0x80000000
help
Embedded SRAM (eSRAM) memory-mapped base address.
config PCIE_ECAM_BASE
hex
default 0xe0000000
config RCBA_BASE
hex
default 0xfed1c000
help
Root Complex register block memory-mapped base address.
config ACPI_PM1_BASE
hex
default 0x1000
help
ACPI Power Managment 1 (PM1) i/o-mapped base address.
This device is defined in ACPI specification, with 16 bytes in size.
config ACPI_PBLK_BASE
hex
default 0x1010
help
ACPI Processor Block (PBLK) i/o-mapped base address.
This device is defined in ACPI specification, with 16 bytes in size.
config SPI_DMA_BASE
hex
default 0x1020
help
SPI DMA i/o-mapped base address.
config GPIO_BASE
hex
default 0x1080
help
GPIO i/o-mapped base address.
config ACPI_GPE0_BASE
hex
default 0x1100
help
ACPI General Purpose Event 0 (GPE0) i/o-mapped base address.
This device is defined in ACPI specification, with 64 bytes in size.
config WDT_BASE
hex
default 0x1140
help
Watchdog timer i/o-mapped base address.
config SYS_CAR_ADDR
hex
default ESRAM_BASE
config SYS_CAR_SIZE
hex
default 0x8000
help
Space in bytes in eSRAM used as Cache-As-ARM (CAR).
Note this size must not exceed eSRAM's total size.
config TSC_FREQ_IN_MHZ
int
default 400
endif

View File

@ -0,0 +1,9 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += car.o dram.o msg_port.o quark.o
obj-y += mrc.o mrc_util.o hte.o smc.o
obj-$(CONFIG_PCI) += pci.o

105
arch/x86/cpu/quark/car.S Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <config.h>
#include <asm/pci.h>
#include <asm/post.h>
#include <asm/arch/quark.h>
#include <asm/arch/msg_port.h>
.globl car_init
car_init:
post_code(POST_CAR_START)
/*
* Quark SoC contains an embedded 512KiB SRAM (eSRAM) that is
* initialized by hardware. eSRAM is the ideal place to be used
* for Cache-As-RAM (CAR) before system memory is available.
*
* Relocate this eSRAM to a suitable location in the physical
* memory map and enable it.
*/
/* Host Memory Bound Register P03h:R08h */
mov $((MSG_PORT_HOST_BRIDGE << 16) | (HM_BOUND << 8)), %eax
mov $(DRAM_BASE + DRAM_MAX_SIZE + ESRAM_SIZE), %edx
lea 1f, %esp
jmp msg_port_write
1:
/* eSRAM Block Page Control Register P05h:R82h */
mov $((MSG_PORT_MEM_MGR << 16) | (ESRAM_BLK_CTRL << 8)), %eax
mov $(ESRAM_BLOCK_MODE | (CONFIG_ESRAM_BASE >> 24)), %edx
lea 2f, %esp
jmp msg_port_write
2:
post_code(POST_CAR_CPU_CACHE)
jmp car_init_ret
msg_port_read:
/*
* Parameter:
* eax[23:16] - Message Port ID
* eax[15:08] - Register Address
*
* Return Value:
* eax - Message Port Register value
*
* Return Address: esp
*/
or $((MSG_OP_READ << 24) | MSG_BYTE_ENABLE), %eax
mov %eax, %ebx
/* Write MCR B0:D0:F0:RD0 */
mov $(PCI_CFG_EN | MSG_CTRL_REG), %eax
mov $PCI_REG_ADDR, %dx
out %eax, %dx
mov $PCI_REG_DATA, %dx
mov %ebx, %eax
out %eax, %dx
/* Read MDR B0:D0:F0:RD4 */
mov $(PCI_CFG_EN | MSG_DATA_REG), %eax
mov $PCI_REG_ADDR, %dx
out %eax, %dx
mov $PCI_REG_DATA, %dx
in %dx, %eax
jmp *%esp
msg_port_write:
/*
* Parameter:
* eax[23:16] - Message Port ID
* eax[15:08] - Register Address
* edx - Message Port Register value to write
*
* Return Address: esp
*/
or $((MSG_OP_WRITE << 24) | MSG_BYTE_ENABLE), %eax
mov %eax, %esi
mov %edx, %edi
/* Write MDR B0:D0:F0:RD4 */
mov $(PCI_CFG_EN | MSG_DATA_REG), %eax
mov $PCI_REG_ADDR, %dx
out %eax, %dx
mov $PCI_REG_DATA, %dx
mov %edi, %eax
out %eax, %dx
/* Write MCR B0:D0:F0:RD0 */
mov $(PCI_CFG_EN | MSG_CTRL_REG), %eax
mov $PCI_REG_ADDR, %dx
out %eax, %dx
mov $PCI_REG_DATA, %dx
mov %esi, %eax
out %eax, %dx
jmp *%esp

134
arch/x86/cpu/quark/dram.c Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <fdtdec.h>
#include <asm/post.h>
#include <asm/arch/mrc.h>
#include <asm/arch/quark.h>
DECLARE_GLOBAL_DATA_PTR;
static int mrc_configure_params(struct mrc_params *mrc_params)
{
const void *blob = gd->fdt_blob;
int node;
int mrc_flags;
node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_QRK_MRC);
if (node < 0) {
debug("%s: Cannot find MRC node\n", __func__);
return -EINVAL;
}
/*
* TODO:
*
* We need support fast boot (MRC cache) in the future.
*
* Set boot mode to cold boot for now
*/
mrc_params->boot_mode = BM_COLD;
/*
* TODO:
*
* We need determine ECC by pin strap state
*
* Disable ECC by default for now
*/
mrc_params->ecc_enables = 0;
mrc_flags = fdtdec_get_int(blob, node, "flags", 0);
if (mrc_flags & MRC_FLAG_SCRAMBLE_EN)
mrc_params->scrambling_enables = 1;
else
mrc_params->scrambling_enables = 0;
mrc_params->dram_width = fdtdec_get_int(blob, node, "dram-width", 0);
mrc_params->ddr_speed = fdtdec_get_int(blob, node, "dram-speed", 0);
mrc_params->ddr_type = fdtdec_get_int(blob, node, "dram-type", 0);
mrc_params->rank_enables = fdtdec_get_int(blob, node, "rank-mask", 0);
mrc_params->channel_enables = fdtdec_get_int(blob, node,
"chan-mask", 0);
mrc_params->channel_width = fdtdec_get_int(blob, node,
"chan-width", 0);
mrc_params->address_mode = fdtdec_get_int(blob, node, "addr-mode", 0);
mrc_params->refresh_rate = fdtdec_get_int(blob, node,
"refresh-rate", 0);
mrc_params->sr_temp_range = fdtdec_get_int(blob, node,
"sr-temp-range", 0);
mrc_params->ron_value = fdtdec_get_int(blob, node,
"ron-value", 0);
mrc_params->rtt_nom_value = fdtdec_get_int(blob, node,
"rtt-nom-value", 0);
mrc_params->rd_odt_value = fdtdec_get_int(blob, node,
"rd-odt-value", 0);
mrc_params->params.density = fdtdec_get_int(blob, node,
"dram-density", 0);
mrc_params->params.cl = fdtdec_get_int(blob, node, "dram-cl", 0);
mrc_params->params.ras = fdtdec_get_int(blob, node, "dram-ras", 0);
mrc_params->params.wtr = fdtdec_get_int(blob, node, "dram-wtr", 0);
mrc_params->params.rrd = fdtdec_get_int(blob, node, "dram-rrd", 0);
mrc_params->params.faw = fdtdec_get_int(blob, node, "dram-faw", 0);
debug("MRC dram_width %d\n", mrc_params->dram_width);
debug("MRC rank_enables %d\n", mrc_params->rank_enables);
debug("MRC ddr_speed %d\n", mrc_params->ddr_speed);
debug("MRC flags: %s\n",
(mrc_params->scrambling_enables) ? "SCRAMBLE_EN" : "");
debug("MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n",
mrc_params->params.density, mrc_params->params.cl,
mrc_params->params.ras, mrc_params->params.wtr,
mrc_params->params.rrd, mrc_params->params.faw);
return 0;
}
int dram_init(void)
{
struct mrc_params mrc_params;
int ret;
memset(&mrc_params, 0, sizeof(struct mrc_params));
ret = mrc_configure_params(&mrc_params);
if (ret)
return ret;
/* Set up the DRAM by calling the memory reference code */
mrc_init(&mrc_params);
if (mrc_params.status)
return -EIO;
gd->ram_size = mrc_params.mem_size;
post_code(POST_DRAM);
return 0;
}
void dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = 0;
gd->bd->bi_dram[0].size = gd->ram_size;
}
/*
* This function looks for the highest region of memory lower than 4GB which
* has enough space for U-Boot where U-Boot is aligned on a page boundary.
* It overrides the default implementation found elsewhere which simply
* picks the end of ram, wherever that may be. The location of the stack,
* the relocation address, and how far U-Boot is moved by relocation are
* set in the global data structure.
*/
ulong board_get_usable_ram_top(ulong total_size)
{
return gd->ram_size;
}

396
arch/x86/cpu/quark/hte.c Normal file
View File

@ -0,0 +1,396 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
#include <common.h>
#include <asm/arch/mrc.h>
#include <asm/arch/msg_port.h>
#include "mrc_util.h"
#include "hte.h"
/**
* Enable HTE to detect all possible errors for the given training parameters
* (per-bit or full byte lane).
*/
static void hte_enable_all_errors(void)
{
msg_port_write(HTE, 0x000200A2, 0xFFFFFFFF);
msg_port_write(HTE, 0x000200A3, 0x000000FF);
msg_port_write(HTE, 0x000200A4, 0x00000000);
}
/**
* Go and read the HTE register in order to find any error
*
* @return: The errors detected in the HTE status register
*/
static u32 hte_check_errors(void)
{
return msg_port_read(HTE, 0x000200A7);
}
/**
* Wait until HTE finishes
*/
static void hte_wait_for_complete(void)
{
u32 tmp;
ENTERFN();
do {} while ((msg_port_read(HTE, 0x00020012) & BIT30) != 0);
tmp = msg_port_read(HTE, 0x00020011);
tmp |= BIT9;
tmp &= ~(BIT12 | BIT13);
msg_port_write(HTE, 0x00020011, tmp);
LEAVEFN();
}
/**
* Clear registers related with errors in the HTE
*/
static void hte_clear_error_regs(void)
{
u32 tmp;
/*
* Clear all HTE errors and enable error checking
* for burst and chunk.
*/
tmp = msg_port_read(HTE, 0x000200A1);
tmp |= BIT8;
msg_port_write(HTE, 0x000200A1, tmp);
}
/**
* Execute a basic single-cache-line memory write/read/verify test using simple
* constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
*
* See hte_basic_write_read() which is the external visible wrapper.
*
* @mrc_params: host structure for all MRC global data
* @addr: memory adress being tested (must hit specific channel/rank)
* @first_run: if set then the HTE registers are configured, otherwise it is
* assumed configuration is done and we just re-run the test
* @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
*
* @return: byte lane failure on each bit (for Quark only bit0 and bit1)
*/
static u16 hte_basic_data_cmp(struct mrc_params *mrc_params, u32 addr,
u8 first_run, u8 mode)
{
u32 pattern;
u32 offset;
if (first_run) {
msg_port_write(HTE, 0x00020020, 0x01B10021);
msg_port_write(HTE, 0x00020021, 0x06000000);
msg_port_write(HTE, 0x00020022, addr >> 6);
msg_port_write(HTE, 0x00020062, 0x00800015);
msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
msg_port_write(HTE, 0x00020061, 0x00030008);
if (mode == WRITE_TRAIN)
pattern = 0xC33C0000;
else /* READ_TRAIN */
pattern = 0xAA5555AA;
for (offset = 0x80; offset <= 0x8F; offset++)
msg_port_write(HTE, offset, pattern);
}
msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
msg_port_write(HTE, 0x00020011, 0x00011000);
msg_port_write(HTE, 0x00020011, 0x00011100);
hte_wait_for_complete();
/*
* Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
* any bytelane errors.
*/
return (hte_check_errors() >> 8) & 0xFF;
}
/**
* Examine a single-cache-line memory with write/read/verify test using multiple
* data patterns (victim-aggressor algorithm).
*
* See hte_write_stress_bit_lanes() which is the external visible wrapper.
*
* @mrc_params: host structure for all MRC global data
* @addr: memory adress being tested (must hit specific channel/rank)
* @loop_cnt: number of test iterations
* @seed_victim: victim data pattern seed
* @seed_aggressor: aggressor data pattern seed
* @victim_bit: should be 0 as auto-rotate feature is in use
* @first_run: if set then the HTE registers are configured, otherwise it is
* assumed configuration is done and we just re-run the test
*
* @return: byte lane failure on each bit (for Quark only bit0 and bit1)
*/
static u16 hte_rw_data_cmp(struct mrc_params *mrc_params, u32 addr,
u8 loop_cnt, u32 seed_victim, u32 seed_aggressor,
u8 victim_bit, u8 first_run)
{
u32 offset;
u32 tmp;
if (first_run) {
msg_port_write(HTE, 0x00020020, 0x00910024);
msg_port_write(HTE, 0x00020023, 0x00810024);
msg_port_write(HTE, 0x00020021, 0x06070000);
msg_port_write(HTE, 0x00020024, 0x06070000);
msg_port_write(HTE, 0x00020022, addr >> 6);
msg_port_write(HTE, 0x00020025, addr >> 6);
msg_port_write(HTE, 0x00020062, 0x0000002A);
msg_port_write(HTE, 0x00020063, seed_victim);
msg_port_write(HTE, 0x00020064, seed_aggressor);
msg_port_write(HTE, 0x00020065, seed_victim);
/*
* Write the pattern buffers to select the victim bit
*
* Start with bit0
*/
for (offset = 0x80; offset <= 0x8F; offset++) {
if ((offset % 8) == victim_bit)
msg_port_write(HTE, offset, 0x55555555);
else
msg_port_write(HTE, offset, 0xCCCCCCCC);
}
msg_port_write(HTE, 0x00020061, 0x00000000);
msg_port_write(HTE, 0x00020066, 0x03440000);
msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
}
tmp = 0x10001000 | (loop_cnt << 16);
msg_port_write(HTE, 0x00020011, tmp);
msg_port_write(HTE, 0x00020011, tmp | BIT8);
hte_wait_for_complete();
/*
* Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
* any bytelane errors.
*/
return (hte_check_errors() >> 8) & 0xFF;
}
/**
* Use HW HTE engine to initialize or test all memory attached to a given DUNIT.
* If flag is MRC_MEM_INIT, this routine writes 0s to all memory locations to
* initialize ECC. If flag is MRC_MEM_TEST, this routine will send an 5AA55AA5
* pattern to all memory locations on the RankMask and then read it back.
* Then it sends an A55AA55A pattern to all memory locations on the RankMask
* and reads it back.
*
* @mrc_params: host structure for all MRC global data
* @flag: MRC_MEM_INIT or MRC_MEM_TEST
*
* @return: errors register showing HTE failures. Also prints out which rank
* failed the HTE test if failure occurs. For rank detection to work,
* the address map must be left in its default state. If MRC changes
* the address map, this function must be modified to change it back
* to default at the beginning, then restore it at the end.
*/
u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag)
{
u32 offset;
int test_num;
int i;
/*
* Clear out the error registers at the start of each memory
* init or memory test run.
*/
hte_clear_error_regs();
msg_port_write(HTE, 0x00020062, 0x00000015);
for (offset = 0x80; offset <= 0x8F; offset++)
msg_port_write(HTE, offset, ((offset & 1) ? 0xA55A : 0x5AA5));
msg_port_write(HTE, 0x00020021, 0x00000000);
msg_port_write(HTE, 0x00020022, (mrc_params->mem_size >> 6) - 1);
msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
msg_port_write(HTE, 0x00020066, 0x03000000);
switch (flag) {
case MRC_MEM_INIT:
/*
* Only 1 write pass through memory is needed
* to initialize ECC
*/
test_num = 1;
break;
case MRC_MEM_TEST:
/* Write/read then write/read with inverted pattern */
test_num = 4;
break;
default:
DPF(D_INFO, "Unknown parameter for flag: %d\n", flag);
return 0xFFFFFFFF;
}
DPF(D_INFO, "hte_mem_init");
for (i = 0; i < test_num; i++) {
DPF(D_INFO, ".");
if (i == 0) {
msg_port_write(HTE, 0x00020061, 0x00000000);
msg_port_write(HTE, 0x00020020, 0x00110010);
} else if (i == 1) {
msg_port_write(HTE, 0x00020061, 0x00000000);
msg_port_write(HTE, 0x00020020, 0x00010010);
} else if (i == 2) {
msg_port_write(HTE, 0x00020061, 0x00010100);
msg_port_write(HTE, 0x00020020, 0x00110010);
} else {
msg_port_write(HTE, 0x00020061, 0x00010100);
msg_port_write(HTE, 0x00020020, 0x00010010);
}
msg_port_write(HTE, 0x00020011, 0x00111000);
msg_port_write(HTE, 0x00020011, 0x00111100);
hte_wait_for_complete();
/* If this is a READ pass, check for errors at the end */
if ((i % 2) == 1) {
/* Return immediately if error */
if (hte_check_errors())
break;
}
}
DPF(D_INFO, "done\n");
return hte_check_errors();
}
/**
* Execute a basic single-cache-line memory write/read/verify test using simple
* constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
*
* @mrc_params: host structure for all MRC global data
* @addr: memory adress being tested (must hit specific channel/rank)
* @first_run: if set then the HTE registers are configured, otherwise it is
* assumed configuration is done and we just re-run the test
* @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
*
* @return: byte lane failure on each bit (for Quark only bit0 and bit1)
*/
u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
u8 first_run, u8 mode)
{
u16 errors;
ENTERFN();
/* Enable all error reporting in preparation for HTE test */
hte_enable_all_errors();
hte_clear_error_regs();
errors = hte_basic_data_cmp(mrc_params, addr, first_run, mode);
LEAVEFN();
return errors;
}
/**
* Examine a single-cache-line memory with write/read/verify test using multiple
* data patterns (victim-aggressor algorithm).
*
* @mrc_params: host structure for all MRC global data
* @addr: memory adress being tested (must hit specific channel/rank)
* @first_run: if set then the HTE registers are configured, otherwise it is
* assumed configuration is done and we just re-run the test
*
* @return: byte lane failure on each bit (for Quark only bit0 and bit1)
*/
u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
u32 addr, u8 first_run)
{
u16 errors;
u8 victim_bit = 0;
ENTERFN();
/* Enable all error reporting in preparation for HTE test */
hte_enable_all_errors();
hte_clear_error_regs();
/*
* Loop through each bit in the bytelane.
*
* Each pass creates a victim bit while keeping all other bits the same
* as aggressors. AVN HTE adds an auto-rotate feature which allows us
* to program the entire victim/aggressor sequence in 1 step.
*
* The victim bit rotates on each pass so no need to have software
* implement a victim bit loop like on VLV.
*/
errors = hte_rw_data_cmp(mrc_params, addr, HTE_LOOP_CNT,
HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED,
victim_bit, first_run);
LEAVEFN();
return errors;
}
/**
* Execute a basic single-cache-line memory write or read.
* This is just for receive enable / fine write-levelling purpose.
*
* @addr: memory adress being tested (must hit specific channel/rank)
* @first_run: if set then the HTE registers are configured, otherwise it is
* assumed configuration is done and we just re-run the test
* @is_write: when non-zero memory write operation executed, otherwise read
*/
void hte_mem_op(u32 addr, u8 first_run, u8 is_write)
{
u32 offset;
u32 tmp;
hte_enable_all_errors();
hte_clear_error_regs();
if (first_run) {
tmp = is_write ? 0x01110021 : 0x01010021;
msg_port_write(HTE, 0x00020020, tmp);
msg_port_write(HTE, 0x00020021, 0x06000000);
msg_port_write(HTE, 0x00020022, addr >> 6);
msg_port_write(HTE, 0x00020062, 0x00800015);
msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
msg_port_write(HTE, 0x00020061, 0x00030008);
for (offset = 0x80; offset <= 0x8F; offset++)
msg_port_write(HTE, offset, 0xC33C0000);
}
msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
msg_port_write(HTE, 0x00020011, 0x00011000);
msg_port_write(HTE, 0x00020011, 0x00011100);
hte_wait_for_complete();
}

44
arch/x86/cpu/quark/hte.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
#ifndef _HTE_H_
#define _HTE_H_
enum {
MRC_MEM_INIT,
MRC_MEM_TEST
};
enum {
READ_TRAIN,
WRITE_TRAIN
};
/*
* EXP_LOOP_CNT field of HTE_CMD_CTL
*
* This CANNOT be less than 4!
*/
#define HTE_LOOP_CNT 5
/* random seed for victim */
#define HTE_LFSR_VICTIM_SEED 0xF294BA21
/* random seed for aggressor */
#define HTE_LFSR_AGRESSOR_SEED 0xEBA7492D
u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag);
u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
u8 first_run, u8 mode);
u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
u32 addr, u8 first_run);
void hte_mem_op(u32 addr, u8 first_run, u8 is_write);
#endif /* _HTE_H_ */

204
arch/x86/cpu/quark/mrc.c Normal file
View File

@ -0,0 +1,204 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
/*
* This is the main Quark Memory Reference Code (MRC)
*
* These functions are generic and should work for any Quark-based board.
*
* MRC requires two data structures to be passed in which are initialized by
* mrc_adjust_params().
*
* The basic flow is as follows:
* 01) Check for supported DDR speed configuration
* 02) Set up Memory Manager buffer as pass-through (POR)
* 03) Set Channel Interleaving Mode and Channel Stride to the most aggressive
* setting possible
* 04) Set up the Memory Controller logic
* 05) Set up the DDR_PHY logic
* 06) Initialise the DRAMs (JEDEC)
* 07) Perform the Receive Enable Calibration algorithm
* 08) Perform the Write Leveling algorithm
* 09) Perform the Read Training algorithm (includes internal Vref)
* 10) Perform the Write Training algorithm
* 11) Set Channel Interleaving Mode and Channel Stride to the desired settings
*
* DRAM unit configuration based on Valleyview MRC.
*/
#include <common.h>
#include <asm/arch/mrc.h>
#include <asm/arch/msg_port.h>
#include "mrc_util.h"
#include "smc.h"
static const struct mem_init init[] = {
{ 0x0101, BM_COLD | BM_FAST | BM_WARM | BM_S3, clear_self_refresh },
{ 0x0200, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_timing_control },
{ 0x0103, BM_COLD | BM_FAST , prog_decode_before_jedec },
{ 0x0104, BM_COLD | BM_FAST , perform_ddr_reset },
{ 0x0300, BM_COLD | BM_FAST | BM_S3, ddrphy_init },
{ 0x0400, BM_COLD | BM_FAST , perform_jedec_init },
{ 0x0105, BM_COLD | BM_FAST , set_ddr_init_complete },
{ 0x0106, BM_FAST | BM_WARM | BM_S3, restore_timings },
{ 0x0106, BM_COLD , default_timings },
{ 0x0500, BM_COLD , rcvn_cal },
{ 0x0600, BM_COLD , wr_level },
{ 0x0120, BM_COLD , prog_page_ctrl },
{ 0x0700, BM_COLD , rd_train },
{ 0x0800, BM_COLD , wr_train },
{ 0x010b, BM_COLD , store_timings },
{ 0x010c, BM_COLD | BM_FAST | BM_WARM | BM_S3, enable_scrambling },
{ 0x010d, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_control },
{ 0x010e, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_dra_drb },
{ 0x010f, BM_WARM | BM_S3, perform_wake },
{ 0x0110, BM_COLD | BM_FAST | BM_WARM | BM_S3, change_refresh_period },
{ 0x0111, BM_COLD | BM_FAST | BM_WARM | BM_S3, set_auto_refresh },
{ 0x0112, BM_COLD | BM_FAST | BM_WARM | BM_S3, ecc_enable },
{ 0x0113, BM_COLD | BM_FAST , memory_test },
{ 0x0114, BM_COLD | BM_FAST | BM_WARM | BM_S3, lock_registers }
};
/* Adjust configuration parameters before initialization sequence */
static void mrc_adjust_params(struct mrc_params *mrc_params)
{
const struct dram_params *dram_params;
uint8_t dram_width;
uint32_t rank_enables;
uint32_t channel_width;
ENTERFN();
/* initially expect success */
mrc_params->status = MRC_SUCCESS;
dram_width = mrc_params->dram_width;
rank_enables = mrc_params->rank_enables;
channel_width = mrc_params->channel_width;
/*
* Setup board layout (must be reviewed as is selecting static timings)
* 0 == R0 (DDR3 x16), 1 == R1 (DDR3 x16),
* 2 == DV (DDR3 x8), 3 == SV (DDR3 x8).
*/
if (dram_width == X8)
mrc_params->board_id = 2; /* select x8 layout */
else
mrc_params->board_id = 0; /* select x16 layout */
/* initially no memory */
mrc_params->mem_size = 0;
/* begin of channel settings */
dram_params = &mrc_params->params;
/*
* Determine column bits:
*
* Column: 11 for 8Gbx8, else 10
*/
mrc_params->column_bits[0] =
((dram_params[0].density == 4) &&
(dram_width == X8)) ? (11) : (10);
/*
* Determine row bits:
*
* 512Mbx16=12 512Mbx8=13
* 1Gbx16=13 1Gbx8=14
* 2Gbx16=14 2Gbx8=15
* 4Gbx16=15 4Gbx8=16
* 8Gbx16=16 8Gbx8=16
*/
mrc_params->row_bits[0] = 12 + (dram_params[0].density) +
(((dram_params[0].density < 4) &&
(dram_width == X8)) ? (1) : (0));
/*
* Determine per-channel memory size:
*
* (For 2 RANKs, multiply by 2)
* (For 16 bit data bus, divide by 2)
*
* DENSITY WIDTH MEM_AVAILABLE
* 512Mb x16 0x008000000 ( 128MB)
* 512Mb x8 0x010000000 ( 256MB)
* 1Gb x16 0x010000000 ( 256MB)
* 1Gb x8 0x020000000 ( 512MB)
* 2Gb x16 0x020000000 ( 512MB)
* 2Gb x8 0x040000000 (1024MB)
* 4Gb x16 0x040000000 (1024MB)
* 4Gb x8 0x080000000 (2048MB)
*/
mrc_params->channel_size[0] = (1 << dram_params[0].density);
mrc_params->channel_size[0] *= (dram_width == X8) ? 2 : 1;
mrc_params->channel_size[0] *= (rank_enables == 0x3) ? 2 : 1;
mrc_params->channel_size[0] *= (channel_width == X16) ? 1 : 2;
/* Determine memory size (convert number of 64MB/512Mb units) */
mrc_params->mem_size += mrc_params->channel_size[0] << 26;
LEAVEFN();
}
static void mrc_mem_init(struct mrc_params *mrc_params)
{
int i;
ENTERFN();
/* MRC started */
mrc_post_code(0x01, 0x00);
if (mrc_params->boot_mode != BM_COLD) {
if (mrc_params->ddr_speed != mrc_params->timings.ddr_speed) {
/* full training required as frequency changed */
mrc_params->boot_mode = BM_COLD;
}
}
for (i = 0; i < ARRAY_SIZE(init); i++) {
uint64_t my_tsc;
if (mrc_params->boot_mode & init[i].boot_path) {
uint8_t major = init[i].post_code >> 8 & 0xff;
uint8_t minor = init[i].post_code >> 0 & 0xff;
mrc_post_code(major, minor);
my_tsc = rdtsc();
init[i].init_fn(mrc_params);
DPF(D_TIME, "Execution time %llx", rdtsc() - my_tsc);
}
}
/* display the timings */
print_timings(mrc_params);
/* MRC complete */
mrc_post_code(0x01, 0xff);
LEAVEFN();
}
void mrc_init(struct mrc_params *mrc_params)
{
ENTERFN();
DPF(D_INFO, "MRC Version %04x %s %s\n", MRC_VERSION,
__DATE__, __TIME__);
/* Set up the data structures used by mrc_mem_init() */
mrc_adjust_params(mrc_params);
/* Initialize system memory */
mrc_mem_init(mrc_params);
LEAVEFN();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
#ifndef _MRC_UTIL_H_
#define _MRC_UTIL_H_
/* Turn on this macro to enable MRC debugging output */
#undef MRC_DEBUG
/* MRC Debug Support */
#define DPF debug_cond
/* debug print type */
#ifdef MRC_DEBUG
#define D_ERROR 0x0001
#define D_INFO 0x0002
#define D_REGRD 0x0004
#define D_REGWR 0x0008
#define D_FCALL 0x0010
#define D_TRN 0x0020
#define D_TIME 0x0040
#else
#define D_ERROR 0
#define D_INFO 0
#define D_REGRD 0
#define D_REGWR 0
#define D_FCALL 0
#define D_TRN 0
#define D_TIME 0
#endif
#define ENTERFN(...) debug_cond(D_FCALL, "<%s>\n", __func__)
#define LEAVEFN(...) debug_cond(D_FCALL, "</%s>\n", __func__)
#define REPORTFN(...) debug_cond(D_FCALL, "<%s/>\n", __func__)
/* Generic Register Bits */
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
#define BIT3 0x00000008
#define BIT4 0x00000010
#define BIT5 0x00000020
#define BIT6 0x00000040
#define BIT7 0x00000080
#define BIT8 0x00000100
#define BIT9 0x00000200
#define BIT10 0x00000400
#define BIT11 0x00000800
#define BIT12 0x00001000
#define BIT13 0x00002000
#define BIT14 0x00004000
#define BIT15 0x00008000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
/* Message Bus Port */
#define MEM_CTLR 0x01
#define HOST_BRIDGE 0x03
#define MEM_MGR 0x05
#define HTE 0x11
#define DDRPHY 0x12
/* number of sample points */
#define SAMPLE_CNT 3
/* number of PIs to increment per sample */
#define SAMPLE_DLY 26
enum {
/* indicates to decrease delays when looking for edge */
BACKWARD,
/* indicates to increase delays when looking for edge */
FORWARD
};
enum {
RCVN,
WDQS,
WDQX,
RDQS,
VREF,
WCMD,
WCTL,
WCLK,
MAX_ALGOS,
};
void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
void mrc_post_code(uint8_t major, uint8_t minor);
void delay_n(uint32_t ns);
void delay_u(uint32_t ms);
void select_mem_mgr(void);
void select_hte(void);
void dram_init_command(uint32_t data);
void dram_wake_command(void);
void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane);
void set_rcvn(uint8_t channel, uint8_t rank,
uint8_t byte_lane, uint32_t pi_count);
uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane);
void set_rdqs(uint8_t channel, uint8_t rank,
uint8_t byte_lane, uint32_t pi_count);
uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
void set_wdqs(uint8_t channel, uint8_t rank,
uint8_t byte_lane, uint32_t pi_count);
uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
void set_wdq(uint8_t channel, uint8_t rank,
uint8_t byte_lane, uint32_t pi_count);
uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane);
void set_wcmd(uint8_t channel, uint32_t pi_count);
uint32_t get_wcmd(uint8_t channel);
void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count);
uint32_t get_wclk(uint8_t channel, uint8_t rank);
void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count);
uint32_t get_wctl(uint8_t channel, uint8_t rank);
void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting);
uint32_t get_vref(uint8_t channel, uint8_t byte_lane);
uint32_t get_addr(uint8_t channel, uint8_t rank);
uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
uint8_t rank, bool rcvn);
void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
uint8_t channel, uint8_t rank, bool rcvn);
uint32_t byte_lane_mask(struct mrc_params *mrc_params);
uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address);
uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address);
void lfsr32(uint32_t *lfsr_ptr);
void clear_pointers(void);
void print_timings(struct mrc_params *mrc_params);
#endif /* _MRC_UTIL_H_ */

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <pci.h>
#include <asm/arch/device.h>
#include <asm/arch/msg_port.h>
void msg_port_setup(int op, int port, int reg)
{
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
(((op) << 24) | ((port) << 16) |
(((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
}
u32 msg_port_read(u8 port, u32 reg)
{
u32 value;
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_READ, port, reg);
pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_write(u8 port, u32 reg, u32 value)
{
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_WRITE, port, reg);
}
u32 msg_port_alt_read(u8 port, u32 reg)
{
u32 value;
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_ALT_READ, port, reg);
pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_alt_write(u8 port, u32 reg, u32 value)
{
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_ALT_WRITE, port, reg);
}
u32 msg_port_io_read(u8 port, u32 reg)
{
u32 value;
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_READ, port, reg);
pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_io_write(u8 port, u32 reg, u32 value)
{
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_WRITE, port, reg);
}

70
arch/x86/cpu/quark/pci.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/arch/device.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,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
hose->region_count = 4;
}
int board_pci_post_scan(struct pci_controller *hose)
{
return 0;
}
int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
{
/*
* TODO:
*
* For some unknown reason, the PCI enumeration process hangs
* when it scans to the PCIe root port 0 (D23:F0) & 1 (D23:F1).
*
* For now we just skip these two devices, and this needs to
* be revisited later.
*/
if (dev == QUARK_HOST_BRIDGE ||
dev == QUARK_PCIE0 || dev == QUARK_PCIE1) {
return 1;
}
return 0;
}

118
arch/x86/cpu/quark/quark.c Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <mmc.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/arch/device.h>
#include <asm/arch/msg_port.h>
#include <asm/arch/quark.h>
static struct pci_device_id mmc_supported[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO },
};
/*
* TODO:
*
* This whole routine should be removed until we fully convert the ICH SPI
* driver to DM and make use of DT to pass the bios control register offset
*/
static void unprotect_spi_flash(void)
{
u32 bc;
bc = pci_read_config32(QUARK_LEGACY_BRIDGE, 0xd8);
bc |= 0x1; /* unprotect the flash */
pci_write_config32(QUARK_LEGACY_BRIDGE, 0xd8, bc);
}
static void quark_setup_bars(void)
{
/* GPIO - D31:F0:R44h */
pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
CONFIG_GPIO_BASE | IO_BAR_EN);
/* ACPI PM1 Block - D31:F0:R48h */
pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
/* GPE0 - D31:F0:R4Ch */
pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
/* WDT - D31:F0:R84h */
pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
CONFIG_WDT_BASE | IO_BAR_EN);
/* RCBA - D31:F0:RF0h */
pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA,
CONFIG_RCBA_BASE | MEM_BAR_EN);
/* ACPI P Block - Msg Port 04:R70h */
msg_port_write(MSG_PORT_RMU, PBLK_BA,
CONFIG_ACPI_PBLK_BASE | IO_BAR_EN);
/* SPI DMA - Msg Port 04:R7Ah */
msg_port_write(MSG_PORT_RMU, SPI_DMA_BA,
CONFIG_SPI_DMA_BASE | IO_BAR_EN);
/* PCIe ECAM */
msg_port_write(MSG_PORT_MEM_ARBITER, AEC_CTRL,
CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
msg_port_write(MSG_PORT_HOST_BRIDGE, HEC_REG,
CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
}
int arch_cpu_init(void)
{
struct pci_controller *hose;
int ret;
post_code(POST_CPU_INIT);
#ifdef CONFIG_SYS_X86_TSC_TIMER
timer_set_base(rdtsc());
#endif
ret = x86_cpu_init_f();
if (ret)
return ret;
ret = pci_early_init_hose(&hose);
if (ret)
return ret;
/*
* Quark SoC has some non-standard BARs (excluding PCI standard BARs)
* which need be initialized with suggested values
*/
quark_setup_bars();
unprotect_spi_flash();
return 0;
}
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
void reset_cpu(ulong addr)
{
/* cold reset */
outb(0x08, PORT_RESET);
}
int cpu_mmc_init(bd_t *bis)
{
return pci_mmc_init("Quark SDHCI", mmc_supported,
ARRAY_SIZE(mmc_supported));
}

2764
arch/x86/cpu/quark/smc.c Normal file

File diff suppressed because it is too large Load Diff

446
arch/x86/cpu/quark/smc.h Normal file
View File

@ -0,0 +1,446 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
#ifndef _SMC_H_
#define _SMC_H_
/* System Memory Controller Register Defines */
/* Memory Controller Message Bus Registers Offsets */
#define DRP 0x00
#define DTR0 0x01
#define DTR1 0x02
#define DTR2 0x03
#define DTR3 0x04
#define DTR4 0x05
#define DPMC0 0x06
#define DPMC1 0x07
#define DRFC 0x08
#define DSCH 0x09
#define DCAL 0x0A
#define DRMC 0x0B
#define PMSTS 0x0C
#define DCO 0x0F
#define DSTAT 0x20
#define SSKPD0 0x4A
#define SSKPD1 0x4B
#define DECCCTRL 0x60
#define DECCSTAT 0x61
#define DECCSBECNT 0x62
#define DECCSBECA 0x68
#define DECCSBECS 0x69
#define DECCDBECA 0x6A
#define DECCDBECS 0x6B
#define DFUSESTAT 0x70
#define SCRMSEED 0x80
#define SCRMLO 0x81
#define SCRMHI 0x82
/* DRAM init command */
#define DCMD_MRS1(rnk, dat) (0 | ((rnk) << 22) | (1 << 3) | ((dat) << 6))
#define DCMD_REF(rnk) (1 | ((rnk) << 22))
#define DCMD_PRE(rnk) (2 | ((rnk) << 22))
#define DCMD_PREA(rnk) (2 | ((rnk) << 22) | (BIT10 << 6))
#define DCMD_ACT(rnk, row) (3 | ((rnk) << 22) | ((row) << 6))
#define DCMD_WR(rnk, col) (4 | ((rnk) << 22) | ((col) << 6))
#define DCMD_RD(rnk, col) (5 | ((rnk) << 22) | ((col) << 6))
#define DCMD_ZQCS(rnk) (6 | ((rnk) << 22))
#define DCMD_ZQCL(rnk) (6 | ((rnk) << 22) | (BIT10 << 6))
#define DCMD_NOP(rnk) (7 | ((rnk) << 22))
#define DDR3_EMRS1_DIC_40 (0)
#define DDR3_EMRS1_DIC_34 (1)
#define DDR3_EMRS1_RTTNOM_0 (0)
#define DDR3_EMRS1_RTTNOM_60 (0x04)
#define DDR3_EMRS1_RTTNOM_120 (0x40)
#define DDR3_EMRS1_RTTNOM_40 (0x44)
#define DDR3_EMRS1_RTTNOM_20 (0x200)
#define DDR3_EMRS1_RTTNOM_30 (0x204)
#define DDR3_EMRS2_RTTWR_60 (1 << 9)
#define DDR3_EMRS2_RTTWR_120 (1 << 10)
/* BEGIN DDRIO Registers */
/* DDR IOs & COMPs */
#define DDRIODQ_BL_OFFSET 0x0800
#define DDRIODQ_CH_OFFSET ((NUM_BYTE_LANES / 2) * DDRIODQ_BL_OFFSET)
#define DDRIOCCC_CH_OFFSET 0x0800
#define DDRCOMP_CH_OFFSET 0x0100
/* CH0-BL01-DQ */
#define DQOBSCKEBBCTL 0x0000
#define DQDLLTXCTL 0x0004
#define DQDLLRXCTL 0x0008
#define DQMDLLCTL 0x000C
#define B0RXIOBUFCTL 0x0010
#define B0VREFCTL 0x0014
#define B0RXOFFSET1 0x0018
#define B0RXOFFSET0 0x001C
#define B1RXIOBUFCTL 0x0020
#define B1VREFCTL 0x0024
#define B1RXOFFSET1 0x0028
#define B1RXOFFSET0 0x002C
#define DQDFTCTL 0x0030
#define DQTRAINSTS 0x0034
#define B1DLLPICODER0 0x0038
#define B0DLLPICODER0 0x003C
#define B1DLLPICODER1 0x0040
#define B0DLLPICODER1 0x0044
#define B1DLLPICODER2 0x0048
#define B0DLLPICODER2 0x004C
#define B1DLLPICODER3 0x0050
#define B0DLLPICODER3 0x0054
#define B1RXDQSPICODE 0x0058
#define B0RXDQSPICODE 0x005C
#define B1RXDQPICODER32 0x0060
#define B1RXDQPICODER10 0x0064
#define B0RXDQPICODER32 0x0068
#define B0RXDQPICODER10 0x006C
#define B01PTRCTL0 0x0070
#define B01PTRCTL1 0x0074
#define B01DBCTL0 0x0078
#define B01DBCTL1 0x007C
#define B0LATCTL0 0x0080
#define B1LATCTL0 0x0084
#define B01LATCTL1 0x0088
#define B0ONDURCTL 0x008C
#define B1ONDURCTL 0x0090
#define B0OVRCTL 0x0094
#define B1OVRCTL 0x0098
#define DQCTL 0x009C
#define B0RK2RKCHGPTRCTRL 0x00A0
#define B1RK2RKCHGPTRCTRL 0x00A4
#define DQRK2RKCTL 0x00A8
#define DQRK2RKPTRCTL 0x00AC
#define B0RK2RKLAT 0x00B0
#define B1RK2RKLAT 0x00B4
#define DQCLKALIGNREG0 0x00B8
#define DQCLKALIGNREG1 0x00BC
#define DQCLKALIGNREG2 0x00C0
#define DQCLKALIGNSTS0 0x00C4
#define DQCLKALIGNSTS1 0x00C8
#define DQCLKGATE 0x00CC
#define B0COMPSLV1 0x00D0
#define B1COMPSLV1 0x00D4
#define B0COMPSLV2 0x00D8
#define B1COMPSLV2 0x00DC
#define B0COMPSLV3 0x00E0
#define B1COMPSLV3 0x00E4
#define DQVISALANECR0TOP 0x00E8
#define DQVISALANECR1TOP 0x00EC
#define DQVISACONTROLCRTOP 0x00F0
#define DQVISALANECR0BL 0x00F4
#define DQVISALANECR1BL 0x00F8
#define DQVISACONTROLCRBL 0x00FC
#define DQTIMINGCTRL 0x010C
/* CH0-ECC */
#define ECCDLLTXCTL 0x2004
#define ECCDLLRXCTL 0x2008
#define ECCMDLLCTL 0x200C
#define ECCB1DLLPICODER0 0x2038
#define ECCB1DLLPICODER1 0x2040
#define ECCB1DLLPICODER2 0x2048
#define ECCB1DLLPICODER3 0x2050
#define ECCB01DBCTL0 0x2078
#define ECCB01DBCTL1 0x207C
#define ECCCLKALIGNREG0 0x20B8
#define ECCCLKALIGNREG1 0x20BC
#define ECCCLKALIGNREG2 0x20C0
/* CH0-CMD */
#define CMDOBSCKEBBCTL 0x4800
#define CMDDLLTXCTL 0x4808
#define CMDDLLRXCTL 0x480C
#define CMDMDLLCTL 0x4810
#define CMDRCOMPODT 0x4814
#define CMDDLLPICODER0 0x4820
#define CMDDLLPICODER1 0x4824
#define CMDCFGREG0 0x4840
#define CMDPTRREG 0x4844
#define CMDCLKALIGNREG0 0x4850
#define CMDCLKALIGNREG1 0x4854
#define CMDCLKALIGNREG2 0x4858
#define CMDPMCONFIG0 0x485C
#define CMDPMDLYREG0 0x4860
#define CMDPMDLYREG1 0x4864
#define CMDPMDLYREG2 0x4868
#define CMDPMDLYREG3 0x486C
#define CMDPMDLYREG4 0x4870
#define CMDCLKALIGNSTS0 0x4874
#define CMDCLKALIGNSTS1 0x4878
#define CMDPMSTS0 0x487C
#define CMDPMSTS1 0x4880
#define CMDCOMPSLV 0x4884
#define CMDBONUS0 0x488C
#define CMDBONUS1 0x4890
#define CMDVISALANECR0 0x4894
#define CMDVISALANECR1 0x4898
#define CMDVISACONTROLCR 0x489C
#define CMDCLKGATE 0x48A0
#define CMDTIMINGCTRL 0x48A4
/* CH0-CLK-CTL */
#define CCOBSCKEBBCTL 0x5800
#define CCRCOMPIO 0x5804
#define CCDLLTXCTL 0x5808
#define CCDLLRXCTL 0x580C
#define CCMDLLCTL 0x5810
#define CCRCOMPODT 0x5814
#define CCDLLPICODER0 0x5820
#define CCDLLPICODER1 0x5824
#define CCDDR3RESETCTL 0x5830
#define CCCFGREG0 0x5838
#define CCCFGREG1 0x5840
#define CCPTRREG 0x5844
#define CCCLKALIGNREG0 0x5850
#define CCCLKALIGNREG1 0x5854
#define CCCLKALIGNREG2 0x5858
#define CCPMCONFIG0 0x585C
#define CCPMDLYREG0 0x5860
#define CCPMDLYREG1 0x5864
#define CCPMDLYREG2 0x5868
#define CCPMDLYREG3 0x586C
#define CCPMDLYREG4 0x5870
#define CCCLKALIGNSTS0 0x5874
#define CCCLKALIGNSTS1 0x5878
#define CCPMSTS0 0x587C
#define CCPMSTS1 0x5880
#define CCCOMPSLV1 0x5884
#define CCCOMPSLV2 0x5888
#define CCCOMPSLV3 0x588C
#define CCBONUS0 0x5894
#define CCBONUS1 0x5898
#define CCVISALANECR0 0x589C
#define CCVISALANECR1 0x58A0
#define CCVISACONTROLCR 0x58A4
#define CCCLKGATE 0x58A8
#define CCTIMINGCTL 0x58AC
/* COMP */
#define CMPCTRL 0x6800
#define SOFTRSTCNTL 0x6804
#define MSCNTR 0x6808
#define NMSCNTRL 0x680C
#define LATCH1CTL 0x6814
#define COMPVISALANECR0 0x681C
#define COMPVISALANECR1 0x6820
#define COMPVISACONTROLCR 0x6824
#define COMPBONUS0 0x6830
#define TCOCNTCTRL 0x683C
#define DQANAODTPUCTL 0x6840
#define DQANAODTPDCTL 0x6844
#define DQANADRVPUCTL 0x6848
#define DQANADRVPDCTL 0x684C
#define DQANADLYPUCTL 0x6850
#define DQANADLYPDCTL 0x6854
#define DQANATCOPUCTL 0x6858
#define DQANATCOPDCTL 0x685C
#define CMDANADRVPUCTL 0x6868
#define CMDANADRVPDCTL 0x686C
#define CMDANADLYPUCTL 0x6870
#define CMDANADLYPDCTL 0x6874
#define CLKANAODTPUCTL 0x6880
#define CLKANAODTPDCTL 0x6884
#define CLKANADRVPUCTL 0x6888
#define CLKANADRVPDCTL 0x688C
#define CLKANADLYPUCTL 0x6890
#define CLKANADLYPDCTL 0x6894
#define CLKANATCOPUCTL 0x6898
#define CLKANATCOPDCTL 0x689C
#define DQSANAODTPUCTL 0x68A0
#define DQSANAODTPDCTL 0x68A4
#define DQSANADRVPUCTL 0x68A8
#define DQSANADRVPDCTL 0x68AC
#define DQSANADLYPUCTL 0x68B0
#define DQSANADLYPDCTL 0x68B4
#define DQSANATCOPUCTL 0x68B8
#define DQSANATCOPDCTL 0x68BC
#define CTLANADRVPUCTL 0x68C8
#define CTLANADRVPDCTL 0x68CC
#define CTLANADLYPUCTL 0x68D0
#define CTLANADLYPDCTL 0x68D4
#define CHNLBUFSTATIC 0x68F0
#define COMPOBSCNTRL 0x68F4
#define COMPBUFFDBG0 0x68F8
#define COMPBUFFDBG1 0x68FC
#define CFGMISCCH0 0x6900
#define COMPEN0CH0 0x6904
#define COMPEN1CH0 0x6908
#define COMPEN2CH0 0x690C
#define STATLEGEN0CH0 0x6910
#define STATLEGEN1CH0 0x6914
#define DQVREFCH0 0x6918
#define CMDVREFCH0 0x691C
#define CLKVREFCH0 0x6920
#define DQSVREFCH0 0x6924
#define CTLVREFCH0 0x6928
#define TCOVREFCH0 0x692C
#define DLYSELCH0 0x6930
#define TCODRAMBUFODTCH0 0x6934
#define CCBUFODTCH0 0x6938
#define RXOFFSETCH0 0x693C
#define DQODTPUCTLCH0 0x6940
#define DQODTPDCTLCH0 0x6944
#define DQDRVPUCTLCH0 0x6948
#define DQDRVPDCTLCH0 0x694C
#define DQDLYPUCTLCH0 0x6950
#define DQDLYPDCTLCH0 0x6954
#define DQTCOPUCTLCH0 0x6958
#define DQTCOPDCTLCH0 0x695C
#define CMDDRVPUCTLCH0 0x6968
#define CMDDRVPDCTLCH0 0x696C
#define CMDDLYPUCTLCH0 0x6970
#define CMDDLYPDCTLCH0 0x6974
#define CLKODTPUCTLCH0 0x6980
#define CLKODTPDCTLCH0 0x6984
#define CLKDRVPUCTLCH0 0x6988
#define CLKDRVPDCTLCH0 0x698C
#define CLKDLYPUCTLCH0 0x6990
#define CLKDLYPDCTLCH0 0x6994
#define CLKTCOPUCTLCH0 0x6998
#define CLKTCOPDCTLCH0 0x699C
#define DQSODTPUCTLCH0 0x69A0
#define DQSODTPDCTLCH0 0x69A4
#define DQSDRVPUCTLCH0 0x69A8
#define DQSDRVPDCTLCH0 0x69AC
#define DQSDLYPUCTLCH0 0x69B0
#define DQSDLYPDCTLCH0 0x69B4
#define DQSTCOPUCTLCH0 0x69B8
#define DQSTCOPDCTLCH0 0x69BC
#define CTLDRVPUCTLCH0 0x69C8
#define CTLDRVPDCTLCH0 0x69CC
#define CTLDLYPUCTLCH0 0x69D0
#define CTLDLYPDCTLCH0 0x69D4
#define FNLUPDTCTLCH0 0x69F0
/* PLL */
#define MPLLCTRL0 0x7800
#define MPLLCTRL1 0x7808
#define MPLLCSR0 0x7810
#define MPLLCSR1 0x7814
#define MPLLCSR2 0x7820
#define MPLLDFT 0x7828
#define MPLLMON0CTL 0x7830
#define MPLLMON1CTL 0x7838
#define MPLLMON2CTL 0x783C
#define SFRTRIM 0x7850
#define MPLLDFTOUT0 0x7858
#define MPLLDFTOUT1 0x785C
#define MASTERRSTN 0x7880
#define PLLLOCKDEL 0x7884
#define SFRDEL 0x7888
#define CRUVISALANECR0 0x78F0
#define CRUVISALANECR1 0x78F4
#define CRUVISACONTROLCR 0x78F8
#define IOSFVISALANECR0 0x78FC
#define IOSFVISALANECR1 0x7900
#define IOSFVISACONTROLCR 0x7904
/* END DDRIO Registers */
/* DRAM Specific Message Bus OpCodes */
#define MSG_OP_DRAM_INIT 0x68
#define MSG_OP_DRAM_WAKE 0xCA
#define SAMPLE_SIZE 6
/* must be less than this number to enable early deadband */
#define EARLY_DB 0x12
/* must be greater than this number to enable late deadband */
#define LATE_DB 0x34
#define CHX_REGS (11 * 4)
#define FULL_CLK 128
#define HALF_CLK 64
#define QRTR_CLK 32
#define MCEIL(num, den) ((uint8_t)((num + den - 1) / den))
#define MMAX(a, b) ((a) > (b) ? (a) : (b))
#define DEAD_LOOP() for (;;);
#define MIN_RDQS_EYE 10 /* in PI Codes */
#define MIN_VREF_EYE 10 /* in VREF Codes */
/* how many RDQS codes to jump while margining */
#define RDQS_STEP 1
/* how many VREF codes to jump while margining */
#define VREF_STEP 1
/* offset into "vref_codes[]" for minimum allowed VREF setting */
#define VREF_MIN 0x00
/* offset into "vref_codes[]" for maximum allowed VREF setting */
#define VREF_MAX 0x3F
#define RDQS_MIN 0x00 /* minimum RDQS delay value */
#define RDQS_MAX 0x3F /* maximum RDQS delay value */
/* how many WDQ codes to jump while margining */
#define WDQ_STEP 1
enum {
B, /* BOTTOM VREF */
T /* TOP VREF */
};
enum {
L, /* LEFT RDQS */
R /* RIGHT RDQS */
};
/* Memory Options */
/* enable STATIC timing settings for RCVN (BACKUP_MODE) */
#undef BACKUP_RCVN
/* enable STATIC timing settings for WDQS (BACKUP_MODE) */
#undef BACKUP_WDQS
/* enable STATIC timing settings for RDQS (BACKUP_MODE) */
#undef BACKUP_RDQS
/* enable STATIC timing settings for WDQ (BACKUP_MODE) */
#undef BACKUP_WDQ
/* enable *COMP overrides (BACKUP_MODE) */
#undef BACKUP_COMPS
/* enable the RD_TRAIN eye check */
#undef RX_EYE_CHECK
/* enable Host to Memory Clock Alignment */
#define HMC_TEST
/* enable multi-rank support via rank2rank sharing */
#define R2R_SHARING
/* disable signals not used in 16bit mode of DDRIO */
#define FORCE_16BIT_DDRIO
#define PLATFORM_ID 1
void clear_self_refresh(struct mrc_params *mrc_params);
void prog_ddr_timing_control(struct mrc_params *mrc_params);
void prog_decode_before_jedec(struct mrc_params *mrc_params);
void perform_ddr_reset(struct mrc_params *mrc_params);
void ddrphy_init(struct mrc_params *mrc_params);
void perform_jedec_init(struct mrc_params *mrc_params);
void set_ddr_init_complete(struct mrc_params *mrc_params);
void restore_timings(struct mrc_params *mrc_params);
void default_timings(struct mrc_params *mrc_params);
void rcvn_cal(struct mrc_params *mrc_params);
void wr_level(struct mrc_params *mrc_params);
void prog_page_ctrl(struct mrc_params *mrc_params);
void rd_train(struct mrc_params *mrc_params);
void wr_train(struct mrc_params *mrc_params);
void store_timings(struct mrc_params *mrc_params);
void enable_scrambling(struct mrc_params *mrc_params);
void prog_ddr_control(struct mrc_params *mrc_params);
void prog_dra_drb(struct mrc_params *mrc_params);
void perform_wake(struct mrc_params *mrc_params);
void change_refresh_period(struct mrc_params *mrc_params);
void set_auto_refresh(struct mrc_params *mrc_params);
void ecc_enable(struct mrc_params *mrc_params);
void memory_test(struct mrc_params *mrc_params);
void lock_registers(struct mrc_params *mrc_params);
#endif /* _SMC_H_ */

View File

@ -11,44 +11,6 @@ config INTEL_QUEENSBAY
if INTEL_QUEENSBAY
config HAVE_FSP
bool "Add an Firmware Support Package binary"
help
Select this option to add an Firmware Support Package binary to
the resulting U-Boot image. It is a binary blob which U-Boot uses
to set up SDRAM and other chipset specific initialization.
Note: Without this binary U-Boot will not be able to set up its
SDRAM so will not boot.
config FSP_FILE
string "Firmware Support Package binary filename"
depends on HAVE_FSP
default "fsp.bin"
help
The filename of the file to use as Firmware Support Package binary
in the board directory.
config FSP_ADDR
hex "Firmware Support Package binary location"
depends on HAVE_FSP
default 0xfffc0000
help
FSP is not Position Independent Code (PIC) and the whole FSP has to
be rebased if it is placed at a location which is different from the
perferred base address specified during the FSP build. Use Intel's
Binary Configuration Tool (BCT) to do the rebase.
The default base address of 0xfffc0000 indicates that the binary must
be located at offset 0xc0000 from the beginning of a 1MB flash device.
config FSP_TEMP_RAM_ADDR
hex
default 0x2000000
help
Stack top address which is used in FspInit after DRAM is ready and
CAR is disabled.
config HAVE_CMC
bool "Add a Chipset Micro Code state machine binary"
help

View File

@ -4,6 +4,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += tnc_car.o tnc_dram.o tnc.o topcliff.o
obj-y += fsp_configs.o fsp_support.o
obj-y += fsp_configs.o
obj-y += tnc.o topcliff.o
obj-$(CONFIG_PCI) += tnc_pci.o

View File

@ -6,7 +6,7 @@
*/
#include <common.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
void update_fsp_upd(struct upd_region *fsp_upd)
{

View File

@ -9,7 +9,7 @@
#include <asm/pci.h>
#include <asm/post.h>
#include <asm/arch/tnc.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
#include <asm/processor.h>
static void unprotect_spi_flash(void)
@ -43,30 +43,3 @@ int arch_cpu_init(void)
return 0;
}
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
void reset_cpu(ulong addr)
{
/* cold reset */
outb(0x06, PORT_RESET);
}
void board_final_cleanup(void)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
status = fsp_notify(NULL, INIT_PHASE_BOOT);
if (status != FSP_SUCCESS)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return;
}

View File

@ -7,7 +7,7 @@
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
@ -44,18 +44,3 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->region_count = 4;
}
int board_pci_post_scan(struct pci_controller *hose)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
status = fsp_notify(NULL, INIT_PHASE_PCI);
if (status != FSP_SUCCESS)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return 0;
}

View File

@ -5,43 +5,16 @@
*/
#include <common.h>
#include <errno.h>
#include <malloc.h>
#include <pci.h>
#include <mmc.h>
#include <pci_ids.h>
#include <sdhci.h>
static struct pci_device_id mmc_supported[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1 },
{ }
};
int cpu_mmc_init(bd_t *bis)
{
struct sdhci_host *mmc_host;
pci_dev_t devbusfn;
u32 iobase;
int ret;
int i;
for (i = 0; i < ARRAY_SIZE(mmc_supported); i++) {
devbusfn = pci_find_devices(mmc_supported, i);
if (devbusfn == -1)
return -ENODEV;
mmc_host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
if (!mmc_host)
return -ENOMEM;
mmc_host->name = "Topcliff SDHCI";
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
mmc_host->ioaddr = (void *)iobase;
mmc_host->quirks = 0;
ret = add_sdhci(mmc_host, 0, 0);
if (ret)
return ret;
}
return 0;
return pci_mmc_init("Topcliff SDHCI", mmc_supported,
ARRAY_SIZE(mmc_supported));
}

View File

@ -1,5 +1,7 @@
dtb-y += chromebook_link.dtb \
crownbay.dtb
crownbay.dtb \
galileo.dtb \
minnowmax.dtb
targets += $(dtb-y)

95
arch/x86/dts/galileo.dts Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
#include <dt-bindings/mrc/quark.h>
/include/ "skeleton.dtsi"
/ {
model = "Intel Galileo";
compatible = "intel,galileo", "intel,quark";
config {
silent_console = <0>;
};
chosen {
stdout-path = &pciuart0;
};
mrc {
compatible = "intel,quark-mrc";
flags = <MRC_FLAG_SCRAMBLE_EN>;
dram-width = <DRAM_WIDTH_X8>;
dram-speed = <DRAM_FREQ_800>;
dram-type = <DRAM_TYPE_DDR3>;
rank-mask = <DRAM_RANK(0)>;
chan-mask = <DRAM_CHANNEL(0)>;
chan-width = <DRAM_CHANNEL_WIDTH_X16>;
addr-mode = <DRAM_ADDR_MODE0>;
refresh-rate = <DRAM_REFRESH_RATE_785US>;
sr-temp-range = <DRAM_SRT_RANGE_NORMAL>;
ron-value = <DRAM_RON_34OHM>;
rtt-nom-value = <DRAM_RTT_NOM_120OHM>;
rd-odt-value = <DRAM_RD_ODT_OFF>;
dram-density = <DRAM_DENSITY_1G>;
dram-cl = <6>;
dram-ras = <0x0000927c>;
dram-wtr = <0x00002710>;
dram-rrd = <0x00002710>;
dram-faw = <0x00009c40>;
};
pci {
#address-cells = <3>;
#size-cells = <2>;
compatible = "intel,pci";
device_type = "pci";
pciuart0: uart@14,5 {
compatible = "pci8086,0936.00",
"pci8086,0936",
"pciclass,070002",
"pciclass,0700",
"x86-uart";
reg = <0x0000a500 0x0 0x0 0x0 0x0
0x0200a510 0x0 0x0 0x0 0x0>;
reg-shift = <2>;
clock-frequency = <44236800>;
current-speed = <115200>;
};
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0 0x20>;
bank-name = "A";
};
gpiob {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x20 0x20>;
bank-name = "B";
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich-spi";
spi-flash@0 {
#size-cells = <1>;
#address-cells = <1>;
reg = <0>;
compatible = "winbond,w25q64", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/ {
model = "Intel Minnowboard Max";
compatible = "intel,minnowmax", "intel,baytrail";
aliases {
serial0 = &serial;
};
config {
silent_console = <0>;
};
chosen {
stdout-path = "/serial";
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich";
spi-flash@0 {
reg = <0>;
compatible = "sst,25vf016b", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
microcode {
update@0 {
#include "microcode/m0130673322.dtsi"
};
};
};

View File

@ -1,5 +1,5 @@
/ {
serial {
serial: serial {
compatible = "x86-uart";
reg = <0x3f8 8>;
reg-shift = <0>;

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: Intel
*/
#ifndef _FSP_AZALIA_H_
#define _FSP_AZALIA_H_
struct __packed pch_azalia_verb_table_header {
uint32_t vendor_device_id;
uint16_t sub_system_id;
uint8_t revision_id; /* 0xff applies to all steppings */
uint8_t front_panel_support;
uint16_t number_of_rear_jacks;
uint16_t number_of_front_jacks;
};
struct __packed pch_azalia_verb_table {
struct pch_azalia_verb_table_header verb_table_header;
const uint32_t *verb_table_data;
};
struct __packed pch_azalia_config {
uint8_t pme_enable:1;
uint8_t docking_supported:1;
uint8_t docking_attached:1;
uint8_t hdmi_codec_enable:1;
uint8_t azalia_v_ci_enable:1;
uint8_t rsvdbits:3;
/* number of verb tables provided by platform */
uint8_t azalia_verb_table_num;
const struct pch_azalia_verb_table *azalia_verb_table;
/* delay timer after azalia reset */
uint16_t reset_wait_timer_us;
};
#endif

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: Intel
*/
#ifndef __FSP_VPD_H
#define __FSP_VPD_H
struct memory_down_data {
uint8_t enable_memory_down;
uint8_t dram_speed;
uint8_t dram_type;
uint8_t dimm_0_enable;
uint8_t dimm_1_enable;
uint8_t dimm_width;
uint8_t dimm_density;
uint8_t dimm_bus_width;
uint8_t dimm_sides; /* Ranks Per dimm_ */
uint8_t dimm_tcl; /* tCL */
/* tRP and tRCD in DRAM clk - 5:12.5ns, 6:15ns, etc. */
uint8_t dimm_trpt_rcd;
uint8_t dimm_twr; /* tWR in DRAM clk */
uint8_t dimm_twtr; /* tWTR in DRAM clk */
uint8_t dimm_trrd; /* tRRD in DRAM clk */
uint8_t dimm_trtp; /* tRTP in DRAM clk */
uint8_t dimm_tfaw; /* tFAW in DRAM clk */
};
struct __packed upd_region {
uint64_t signature; /* Offset 0x0000 */
uint8_t reserved0[24]; /* Offset 0x0008 */
uint16_t mrc_init_tseg_size; /* Offset 0x0020 */
uint16_t mrc_init_mmio_size; /* Offset 0x0022 */
uint8_t mrc_init_spd_addr1; /* Offset 0x0024 */
uint8_t mrc_init_spd_addr2; /* Offset 0x0025 */
uint8_t emmc_boot_mode; /* Offset 0x0026 */
uint8_t enable_sdio; /* Offset 0x0027 */
uint8_t enable_sdcard; /* Offset 0x0028 */
uint8_t enable_hsuart0; /* Offset 0x0029 */
uint8_t enable_hsuart1; /* Offset 0x002a */
uint8_t enable_spi; /* Offset 0x002b */
uint8_t reserved1; /* Offset 0x002c */
uint8_t enable_sata; /* Offset 0x002d */
uint8_t sata_mode; /* Offset 0x002e */
uint8_t enable_azalia; /* Offset 0x002f */
uint32_t azalia_config_ptr; /* Offset 0x0030 */
uint8_t enable_xhci; /* Offset 0x0034 */
uint8_t enable_lpe; /* Offset 0x0035 */
uint8_t lpss_sio_enable_pci_mode; /* Offset 0x0036 */
uint8_t enable_dma0; /* Offset 0x0037 */
uint8_t enable_dma1; /* Offset 0x0038 */
uint8_t enable_i2_c0; /* Offset 0x0039 */
uint8_t enable_i2_c1; /* Offset 0x003a */
uint8_t enable_i2_c2; /* Offset 0x003b */
uint8_t enable_i2_c3; /* Offset 0x003c */
uint8_t enable_i2_c4; /* Offset 0x003d */
uint8_t enable_i2_c5; /* Offset 0x003e */
uint8_t enable_i2_c6; /* Offset 0x003f */
uint8_t enable_pwm0; /* Offset 0x0040 */
uint8_t enable_pwm1; /* Offset 0x0041 */
uint8_t enable_hsi; /* Offset 0x0042 */
uint8_t igd_dvmt50_pre_alloc; /* Offset 0x0043 */
uint8_t aperture_size; /* Offset 0x0044 */
uint8_t gtt_size; /* Offset 0x0045 */
uint32_t serial_debug_port_address; /* Offset 0x0046 */
uint8_t serial_debug_port_type; /* Offset 0x004a */
uint8_t mrc_debug_msg; /* Offset 0x004b */
uint8_t isp_enable; /* Offset 0x004c */
uint8_t scc_enable_pci_mode; /* Offset 0x004d */
uint8_t igd_render_standby; /* Offset 0x004e */
uint8_t txe_uma_enable; /* Offset 0x004f */
uint8_t os_selection; /* Offset 0x0050 */
uint8_t emmc45_ddr50_enabled; /* Offset 0x0051 */
uint8_t emmc45_hs200_enabled; /* Offset 0x0052 */
uint8_t emmc45_retune_timer_value; /* Offset 0x0053 */
uint8_t unused_upd_space1[156]; /* Offset 0x0054 */
struct memory_down_data memory_params; /* Offset 0x00f0 */
uint16_t terminator; /* Offset 0x0100 */
};
#define VPD_IMAGE_ID 0x3157454956594C56 /* 'VLYVIEW1' */
#define VPD_IMAGE_REV 0x00000303
struct __packed vpd_region {
uint64_t sign; /* Offset 0x0000 */
uint32_t img_rev; /* Offset 0x0008 */
uint32_t upd_offset; /* Offset 0x000c */
uint8_t unused[16]; /* Offset 0x0010 */
uint32_t fsp_res_memlen; /* Offset 0x0020 */
uint8_t platform_type; /* Offset 0x0024 */
uint8_t enable_secure_boot; /* Offset 0x0025 */
};
#endif

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _X86_ARCH_GPIO_H_
#define _X86_ARCH_GPIO_H_
/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x44
#endif /* _X86_ARCH_GPIO_H_ */

View File

@ -43,7 +43,7 @@
#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */
#define DEFAULT_RCBABASE 0xfed1c000
/* 4 KB per PCIe device */
#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS
#define DEFAULT_PCIEXBAR CONFIG_PCIE_ECAM_BASE
/* Device 0:0.0 PCI configuration space (Host Bridge) */
#define EPBAR 0x40

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _QUARK_DEVICE_H_
#define _QUARK_DEVICE_H_
#include <pci.h>
#define QUARK_HOST_BRIDGE PCI_BDF(0, 0, 0)
#define QUARK_MMC_SDIO PCI_BDF(0, 20, 0)
#define QUARK_UART0 PCI_BDF(0, 20, 1)
#define QUARK_USB_DEVICE PCI_BDF(0, 20, 2)
#define QUARK_USB_EHCI PCI_BDF(0, 20, 3)
#define QUARK_USB_OHCI PCI_BDF(0, 20, 4)
#define QUARK_UART1 PCI_BDF(0, 20, 5)
#define QUARK_EMAC0 PCI_BDF(0, 20, 6)
#define QUARK_EMAC1 PCI_BDF(0, 20, 7)
#define QUARK_SPI0 PCI_BDF(0, 21, 0)
#define QUARK_SPI1 PCI_BDF(0, 21, 1)
#define QUARK_I2C_GPIO PCI_BDF(0, 21, 2)
#define QUARK_PCIE0 PCI_BDF(0, 23, 0)
#define QUARK_PCIE1 PCI_BDF(0, 23, 1)
#define QUARK_LEGACY_BRIDGE PCI_BDF(0, 31, 0)
#endif /* _QUARK_DEVICE_H_ */

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _X86_ARCH_GPIO_H_
#define _X86_ARCH_GPIO_H_
/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x44
#endif /* _X86_ARCH_GPIO_H_ */

View File

@ -0,0 +1,187 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Ported from Intel released Quark UEFI BIOS
* QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
*
* SPDX-License-Identifier: Intel
*/
#ifndef _MRC_H_
#define _MRC_H_
#define MRC_VERSION 0x0111
/* architectural definitions */
#define NUM_CHANNELS 1 /* number of channels */
#define NUM_RANKS 2 /* number of ranks per channel */
#define NUM_BYTE_LANES 4 /* number of byte lanes per channel */
/* software limitations */
#define MAX_CHANNELS 1
#define MAX_RANKS 2
#define MAX_BYTE_LANES 4
#define MAX_SOCKETS 1
#define MAX_SIDES 1
#define MAX_ROWS (MAX_SIDES * MAX_SOCKETS)
/* Specify DRAM and channel width */
enum {
X8, /* DRAM width */
X16, /* DRAM width & Channel Width */
X32 /* Channel Width */
};
/* Specify DRAM speed */
enum {
DDRFREQ_800,
DDRFREQ_1066
};
/* Specify DRAM type */
enum {
DDR3,
DDR3L
};
/*
* density: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
* cl: DRAM CAS Latency in clocks
* ras: ACT to PRE command period
* wtr: Delay from start of internal write transaction to internal read command
* rrd: ACT to ACT command period (JESD79 specific to page size 1K/2K)
* faw: Four activate window (JESD79 specific to page size 1K/2K)
*
* ras/wtr/rrd/faw timings are in picoseconds
*
* Refer to JEDEC spec (or DRAM datasheet) when changing these values.
*/
struct dram_params {
uint8_t density;
uint8_t cl;
uint32_t ras;
uint32_t wtr;
uint32_t rrd;
uint32_t faw;
};
/*
* Delay configuration for individual signals
* Vref setting
* Scrambler seed
*/
struct mrc_timings {
uint32_t rcvn[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
uint32_t rdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
uint32_t wdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
uint32_t wdq[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
uint32_t vref[NUM_CHANNELS][NUM_BYTE_LANES];
uint32_t wctl[NUM_CHANNELS][NUM_RANKS];
uint32_t wcmd[NUM_CHANNELS];
uint32_t scrambler_seed;
/* need to save for the case of frequency change */
uint8_t ddr_speed;
};
/* Boot mode defined as bit mask (1<<n) */
enum {
BM_UNKNOWN,
BM_COLD = 1, /* full training */
BM_FAST = 2, /* restore timing parameters */
BM_S3 = 4, /* resume from S3 */
BM_WARM = 8
};
/* MRC execution status */
#define MRC_SUCCESS 0 /* initialization ok */
#define MRC_E_MEMTEST 1 /* memtest failed */
/*
* Memory Reference Code parameters
*
* It includes 3 parts:
* - input parameters like boot mode and DRAM parameters
* - context parameters for MRC internal state
* - output parameters like initialization result and memory size
*/
struct mrc_params {
/* Input parameters */
uint32_t boot_mode; /* BM_COLD, BM_FAST, BM_WARM, BM_S3 */
/* DRAM parameters */
uint8_t dram_width; /* x8, x16 */
uint8_t ddr_speed; /* DDRFREQ_800, DDRFREQ_1066 */
uint8_t ddr_type; /* DDR3, DDR3L */
uint8_t ecc_enables; /* 0, 1 (memory size reduced to 7/8) */
uint8_t scrambling_enables; /* 0, 1 */
/* 1, 3 (1'st rank has to be populated if 2'nd rank present) */
uint32_t rank_enables;
uint32_t channel_enables; /* 1 only */
uint32_t channel_width; /* x16 only */
/* 0, 1, 2 (mode 2 forced if ecc enabled) */
uint32_t address_mode;
/* REFRESH_RATE: 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED */
uint8_t refresh_rate;
/* SR_TEMP_RANGE: 0=normal, 1=extended, others=RESERVED */
uint8_t sr_temp_range;
/*
* RON_VALUE: 0=34ohm, 1=40ohm, others=RESERVED
* (select MRS1.DIC driver impedance control)
*/
uint8_t ron_value;
/* RTT_NOM_VALUE: 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED */
uint8_t rtt_nom_value;
/* RD_ODT_VALUE: 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED */
uint8_t rd_odt_value;
struct dram_params params;
/* Internally used context parameters */
uint32_t board_id; /* board layout (use x8 or x16 memory) */
uint32_t hte_setup; /* when set hte reconfiguration requested */
uint32_t menu_after_mrc;
uint32_t power_down_disable;
uint32_t tune_rcvn;
uint32_t channel_size[NUM_CHANNELS];
uint32_t column_bits[NUM_CHANNELS];
uint32_t row_bits[NUM_CHANNELS];
uint32_t mrs1; /* register content saved during training */
uint8_t first_run;
/* Output parameters */
/* initialization result (non zero specifies error code) */
uint32_t status;
/* total memory size in bytes (excludes ECC banks) */
uint32_t mem_size;
/* training results (also used on input) */
struct mrc_timings timings;
};
/*
* MRC memory initialization structure
*
* post_code: a 16-bit post code of a specific initialization routine
* boot_path: bitwise or of BM_COLD, BM_FAST, BM_WARM and BM_S3
* init_fn: real memory initialization routine
*/
struct mem_init {
uint16_t post_code;
uint16_t boot_path;
void (*init_fn)(struct mrc_params *mrc_params);
};
/* MRC platform data flags */
#define MRC_FLAG_ECC_EN 0x00000001
#define MRC_FLAG_SCRAMBLE_EN 0x00000002
#define MRC_FLAG_MEMTEST_EN 0x00000004
/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
#define MRC_FLAG_TOP_TREE_EN 0x00000008
/* If set ODR signal is asserted to DRAM devices on writes */
#define MRC_FLAG_WR_ODT_EN 0x00000010
/**
* mrc_init - Memory Reference Code initialization entry routine
*
* @mrc_params: parameters for MRC
*/
void mrc_init(struct mrc_params *mrc_params);
#endif /* _MRC_H_ */

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _QUARK_MSG_PORT_H_
#define _QUARK_MSG_PORT_H_
/*
* In the Quark SoC, some chipset commands are accomplished by utilizing
* the internal message network within the host bridge (D0:F0). Accesses
* to this network are accomplished by populating the message control
* register (MCR), Message Control Register eXtension (MCRX) and the
* message data register (MDR).
*/
#define MSG_CTRL_REG 0xd0 /* Message Control Register */
#define MSG_DATA_REG 0xd4 /* Message Data Register */
#define MSG_CTRL_EXT_REG 0xd8 /* Message Control Register EXT */
/* Normal Read/Write OpCodes */
#define MSG_OP_READ 0x10
#define MSG_OP_WRITE 0x11
/* Alternative Read/Write OpCodes */
#define MSG_OP_ALT_READ 0x06
#define MSG_OP_ALT_WRITE 0x07
/* IO Read/Write OpCodes */
#define MSG_OP_IO_READ 0x02
#define MSG_OP_IO_WRITE 0x03
/* All byte enables */
#define MSG_BYTE_ENABLE 0xf0
#ifndef __ASSEMBLY__
/**
* msg_port_setup - set up the message port control register
*
* @op: message bus access opcode
* @port: port number on the message bus
* @reg: register number within a port
*/
void msg_port_setup(int op, int port, int reg);
/**
* msg_port_read - read a message port register using normal opcode
*
* @port: port number on the message bus
* @reg: register number within a port
*
* @return: message port register value
*/
u32 msg_port_read(u8 port, u32 reg);
/**
* msg_port_write - write a message port register using normal opcode
*
* @port: port number on the message bus
* @reg: register number within a port
* @value: register value to write
*/
void msg_port_write(u8 port, u32 reg, u32 value);
/**
* msg_port_alt_read - read a message port register using alternative opcode
*
* @port: port number on the message bus
* @reg: register number within a port
*
* @return: message port register value
*/
u32 msg_port_alt_read(u8 port, u32 reg);
/**
* msg_port_alt_write - write a message port register using alternative opcode
*
* @port: port number on the message bus
* @reg: register number within a port
* @value: register value to write
*/
void msg_port_alt_write(u8 port, u32 reg, u32 value);
/**
* msg_port_io_read - read a message port register using I/O opcode
*
* @port: port number on the message bus
* @reg: register number within a port
*
* @return: message port register value
*/
u32 msg_port_io_read(u8 port, u32 reg);
/**
* msg_port_io_write - write a message port register using I/O opcode
*
* @port: port number on the message bus
* @reg: register number within a port
* @value: register value to write
*/
void msg_port_io_write(u8 port, u32 reg, u32 value);
#endif /* __ASSEMBLY__ */
#endif /* _QUARK_MSG_PORT_H_ */

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _QUARK_H_
#define _QUARK_H_
/* Message Bus Ports */
#define MSG_PORT_MEM_ARBITER 0x00
#define MSG_PORT_HOST_BRIDGE 0x03
#define MSG_PORT_RMU 0x04
#define MSG_PORT_MEM_MGR 0x05
#define MSG_PORT_SOC_UNIT 0x31
/* Port 0x00: Memory Arbiter Message Port Registers */
/* Enhanced Configuration Space */
#define AEC_CTRL 0x00
/* Port 0x03: Host Bridge Message Port Registers */
/* Host Memory I/O Boundary */
#define HM_BOUND 0x08
/* Extended Configuration Space */
#define HEC_REG 0x09
/* Port 0x04: Remote Management Unit Message Port Registers */
/* ACPI PBLK Base Address Register */
#define PBLK_BA 0x70
/* SPI DMA Base Address Register */
#define SPI_DMA_BA 0x7a
/* Port 0x05: Memory Manager Message Port Registers */
/* eSRAM Block Page Control */
#define ESRAM_BLK_CTRL 0x82
#define ESRAM_BLOCK_MODE 0x10000000
/* DRAM */
#define DRAM_BASE 0x00000000
#define DRAM_MAX_SIZE 0x80000000
/* eSRAM */
#define ESRAM_SIZE 0x80000
/* Memory BAR Enable */
#define MEM_BAR_EN 0x00000001
/* I/O BAR Enable */
#define IO_BAR_EN 0x80000000
/* 64KiB of RMU binary in flash */
#define RMU_BINARY_SIZE 0x10000
/* Legacy Bridge PCI Configuration Registers */
#define LB_GBA 0x44
#define LB_PM1BLK 0x48
#define LB_GPE0BLK 0x4c
#define LB_ACTL 0x58
#define LB_PABCDRC 0x60
#define LB_PEFGHRC 0x64
#define LB_WDTBA 0x84
#define LB_BCE 0xd4
#define LB_BC 0xd8
#define LB_RCBA 0xf0
#endif /* _QUARK_H_ */

View File

@ -10,8 +10,6 @@
#ifndef __VPDHEADER_H__
#define __VPDHEADER_H__
#define UPD_TERMINATOR 0x55AA
struct __packed upd_region {
u64 sign; /* Offset 0x0000 */
u64 reserved; /* Offset 0x0008 */

View File

@ -8,6 +8,8 @@
#ifndef __FSP_API_H__
#define __FSP_API_H__
#include <linux/linkage.h>
/*
* FspInit continuation function prototype.
* Control will be returned to this callback function after FspInit API call.
@ -47,9 +49,9 @@ struct fsp_notify_params {
};
/* FspInit API function prototype */
typedef u32 (*fsp_init_f)(struct fsp_init_params *params);
typedef asmlinkage u32 (*fsp_init_f)(struct fsp_init_params *params);
/* FspNotify API function prototype */
typedef u32 (*fsp_notify_f)(struct fsp_notify_params *params);
typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
#endif

View File

@ -16,7 +16,7 @@
#include "fsp_platform.h"
#include "fsp_infoheader.h"
#include "fsp_bootmode.h"
#include "fsp_vpd.h"
#include <asm/arch/fsp/fsp_vpd.h>
struct shared_data {
struct fsp_header *fsp_hdr;
@ -26,6 +26,8 @@ struct shared_data {
#define FSP_LOWMEM_BASE 0x100000UL
#define FSP_HIGHMEM_BASE 0x100000000ULL
#define UPD_TERMINATOR 0x55AA
/**
* FSP Continuation assembly helper routine
@ -61,7 +63,7 @@ void fsp_continue(struct shared_data *shared_data, u32 status,
*
* @retval: the offset of FSP header. If signature is invalid, returns 0.
*/
u32 find_fsp_header(void);
struct fsp_header *find_fsp_header(void);
/**
* FSP initialization wrapper function.

View File

@ -1,4 +1,3 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
@ -9,6 +8,14 @@
#ifndef _PCI_I386_H_
#define _PCI_I386_H_
/* bus mapping constants (used for PCI core initialization) */
#define PCI_REG_ADDR 0xcf8
#define PCI_REG_DATA 0xcfc
#define PCI_CFG_EN 0x80000000
#ifndef __ASSEMBLY__
#define DEFINE_PCI_DEVICE_TABLE(_table) \
const struct pci_device_id _table[]
@ -49,4 +56,6 @@ void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value);
void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value);
void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value);
#endif
#endif /* __ASSEMBLY__ */
#endif /* _PCI_I386_H_ */

View File

@ -39,6 +39,9 @@ ulong board_get_usable_ram_top(ulong total_size);
void dram_init_banksize(void);
int default_print_cpuinfo(void);
/* Set up a UART which can be used with printch(), printhex8(), etc. */
int setup_early_uart(void);
void setup_pcat_compatibility(void);
void isa_unmap_rom(u32 addr);

View File

@ -25,6 +25,7 @@ obj-y += string.o
obj-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o
obj-$(CONFIG_VIDEO_VGA) += video.o
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
obj-$(CONFIG_HAVE_FSP) += fsp/
extra-$(CONFIG_USE_PRIVATE_LIBGCC) := lib.a

View File

@ -7,7 +7,7 @@
#include <common.h>
#include <command.h>
#include <linux/compiler.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;

10
arch/x86/lib/fsp/Makefile Normal file
View File

@ -0,0 +1,10 @@
#
# Copyright (C) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += fsp_car.o
obj-y += fsp_common.o
obj-y += fsp_dram.o
obj-y += fsp_support.o

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/fsp/fsp_support.h>
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
void reset_cpu(ulong addr)
{
/* cold reset */
outb(0x06, PORT_RESET);
}
int board_pci_post_scan(struct pci_controller *hose)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
status = fsp_notify(NULL, INIT_PHASE_PCI);
if (status != FSP_SUCCESS)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return 0;
}
void board_final_cleanup(void)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
status = fsp_notify(NULL, INIT_PHASE_BOOT);
if (status != FSP_SUCCESS)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return;
}

View File

@ -5,7 +5,7 @@
*/
#include <common.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
#include <asm/e820.h>
#include <asm/post.h>

View File

@ -6,7 +6,7 @@
*/
#include <common.h>
#include <asm/arch/fsp/fsp_support.h>
#include <asm/fsp/fsp_support.h>
#include <asm/post.h>
/**
@ -30,7 +30,7 @@ static bool compare_guid(const struct efi_guid *guid1,
return false;
}
u32 __attribute__((optimize("O0"))) find_fsp_header(void)
struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
{
/*
* This function may be called before the a stack is established,
@ -84,7 +84,7 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void)
fsp = 0;
}
return (u32)fsp;
return (struct fsp_header *)fsp;
}
void fsp_continue(struct shared_data *shared_data, u32 status, void *hob_list)
@ -124,25 +124,29 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
struct fsp_init_params *params_ptr;
struct upd_region *fsp_upd;
fsp_hdr = (struct fsp_header *)find_fsp_header();
#ifdef CONFIG_DEBUG_UART
setup_early_uart();
#endif
fsp_hdr = find_fsp_header();
if (fsp_hdr == NULL) {
/* No valid FSP info header was found */
panic("Invalid FSP header");
}
fsp_upd = (struct upd_region *)&shared_data.fsp_upd;
fsp_upd = &shared_data.fsp_upd;
memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
/* Reserve a gap in stack top */
rt_buf.common.stack_top = (u32 *)stack_top - 32;
rt_buf.common.boot_mode = boot_mode;
rt_buf.common.upd_data = (struct upd_region *)fsp_upd;
rt_buf.common.upd_data = fsp_upd;
/* Get VPD region start */
fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
fsp_hdr->cfg_region_off);
/* Verifify the VPD data region is valid */
/* Verify the VPD data region is valid */
assert((fsp_vpd->img_rev == VPD_IMAGE_REV) &&
(fsp_vpd->sign == VPD_IMAGE_ID));
@ -150,7 +154,7 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
sizeof(struct upd_region));
/* Verifify the UPD data region is valid */
/* Verify the UPD data region is valid */
assert(fsp_upd->terminator == UPD_TERMINATOR);
/* Override any UPD setting if required */

View File

@ -12,6 +12,7 @@
#include <common.h>
#include <asm/io.h>
#include <pci.h>
#include <asm/pci.h>
#define cfg_read(val, addr, op) (*val = op((int)(addr)))
#define cfg_write(val, addr, op) op((val), (int)(addr))
@ -21,7 +22,7 @@ static int \
type1_##rw##_config_##size(struct pci_controller *hose, \
pci_dev_t dev, int offset, type val) \
{ \
outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr); \
outl(dev | (offset & 0xfc) | PCI_CFG_EN, (int)hose->cfg_addr); \
cfg_##rw(val, hose->cfg_data + (offset & mask), op); \
return 0; \
}
@ -34,10 +35,6 @@ TYPE1_PCI_OP(write, byte, u8, outb, 3)
TYPE1_PCI_OP(write, word, u16, outw, 2)
TYPE1_PCI_OP(write, dword, u32, outl, 0)
/* bus mapping constants (used for PCI core initialization) */
#define PCI_REG_ADDR 0x00000cf8
#define PCI_REG_DATA 0x00000cfc
void pci_setup_type1(struct pci_controller *hose)
{
pci_set_ops(hose,

View File

@ -22,8 +22,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
config MMCONF_BASE_ADDRESS
hex
config PCIE_ECAM_BASE
default 0xf0000000
config EARLY_POST_CROS_EC

View File

@ -0,0 +1,21 @@
if TARGET_GALILEO
config SYS_BOARD
default "galileo"
config SYS_VENDOR
default "intel"
config SYS_SOC
default "quark"
config SYS_CONFIG_NAME
default "galileo"
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select INTEL_QUARK
select BOARD_ROMSIZE_KB_1024
endif

View File

@ -0,0 +1,6 @@
INTEL GALILEO BOARD
M: Bin Meng <bmeng.cn@gmail.com>
S: Maintained
F: board/intel/galileo/
F: include/configs/galileo.h
F: configs/galileo_defconfig

View File

@ -0,0 +1,7 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += galileo.o start.o

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
int board_early_init_f(void)
{
return 0;
}
void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
{
return;
}

View File

@ -0,0 +1,9 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl early_board_init
early_board_init:
jmp early_board_init_ret

View File

@ -0,0 +1,24 @@
if TARGET_MINNOWMAX
config SYS_BOARD
default "minnowmax"
config SYS_VENDOR
default "intel"
config SYS_SOC
default "baytrail"
config SYS_CONFIG_NAME
default "minnowmax"
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select INTEL_BAYTRAIL
select BOARD_ROMSIZE_KB_8192
config PCIE_ECAM_BASE
default 0xe0000000
endif

View File

@ -0,0 +1,6 @@
CircuitCo Minnowboard Max
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/intel/minnowmax
F: include/configs/minnowmax.h
F: configs/minnowmax_defconfig

View File

@ -0,0 +1,7 @@
#
# Copyright (C) 2015, Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += minnowmax.o start.o

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015, Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/ibmpc.h>
#include <asm/pnp_def.h>
#include <netdev.h>
#include <smsc_lpc47m.h>
#define SERIAL_DEV PNP_DEV(0x2e, 4)
DECLARE_GLOBAL_DATA_PTR;
int board_early_init_f(void)
{
lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
return 0;
}
void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
{
return;
}
int board_eth_init(bd_t *bis)
{
return pci_eth_init(bis);
}

View File

@ -0,0 +1,9 @@
/*
* Copyright (C) 2015, Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl early_board_init
early_board_init:
jmp early_board_init_ret

View File

@ -217,8 +217,10 @@ void scsi_init(void)
(busdevfunc >> 8) & 0x7);
}
#endif
bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
scsi_low_level_init(busdevfunc);
scsi_scan(1);
bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
}
#endif

View File

@ -0,0 +1,6 @@
CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff10000"
CONFIG_X86=y
CONFIG_TARGET_GALILEO=y
CONFIG_OF_CONTROL=y
CONFIG_OF_SEPARATE=y
CONFIG_DEFAULT_DEVICE_TREE="galileo"

View File

@ -0,0 +1,13 @@
CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff00000"
CONFIG_X86=y
CONFIG_TARGET_MINNOWMAX=y
CONFIG_OF_CONTROL=y
CONFIG_OF_SEPARATE=y
CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
CONFIG_VIDEO_X86=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
CONFIG_DEBUG_UART_NS16550=y
CONFIG_DEBUG_UART=y
CONFIG_MMCONF_BASE_ADDRESS=0xe0000000
CONFIG_HAVE_INTEL_ME=y

View File

@ -18,11 +18,11 @@ U-Boot supports running as a coreboot [1] payload on x86. So far only Link
on other x86 boards since coreboot deals with most of the low-level details.
U-Boot also supports booting directly from x86 reset vector without coreboot,
aka raw support or bare support. Currently Link and Intel Crown Bay board
support running U-Boot 'bare metal'.
aka raw support or bare support. Currently Link, Intel Crown Bay, Intel
Minnowboard Max and Intel Galileo support running U-Boot 'bare metal'.
As for loading OS, U-Boot supports directly booting a 32-bit or 64-bit Linux
kernel as part of a FIT image. It also supports a compressed zImage.
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit
Linux kernel as part of a FIT image. It also supports a compressed zImage.
Build Instructions
------------------
@ -47,13 +47,15 @@ Change the 'Board configuration file' and 'Board Device Tree Source (dts) file'
to point to a new board. You can also change the Cache-As-RAM (CAR) related
settings here if the default values do not fit your new board.
Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
Building a ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
little bit tricky, as generally it requires several binary blobs which are not
shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is
not turned on by default in the U-Boot source tree. Firstly, you need turn it
on by uncommenting the following line in the main U-Boot Makefile:
on by enabling the ROM build:
# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
$ export BUILD_ROM=y
This tells the Makefile to build u-boot.rom as a target.
Link-specific instructions:
@ -108,6 +110,50 @@ Now you can build U-Boot and obtain u-boot.rom
$ make crownbay_defconfig
$ make all
Intel Minnowboard Max instructions:
This uses as FSP as with Crown Bay, except it is for the Atom E3800 series.
Download this and get the .fd file (BAYTRAIL_FSP_GOLD_003_16-SEP-2014.fd at
the time of writing). Put it in the board directory:
board/intel/minnowmax/fsp.bin
Obtain the VGA RAM (Vga.dat at the time of writing) and put it into the same
directory: board/intel/minnowmax/vga.bin
You still need two more binary blobs. These come from the sample SPI image
provided in the FSP (SPI.bin at the time of writing).
Use ifdtool in the U-Boot tools directory to extract the images from that
file, for example:
$ ./tools/ifdtool -x BayleyBay/SPI.bin
$ cp flashregion_2_intel_me.bin board/intel/minnowmax/me.bin
$ cp flashregion_0_flashdescriptor.bin board/intel/minnowmax/descriptor.bin
Now you can build U-Boot and obtain u-boot.rom
$ make minnowmax_defconfig
$ make all
Intel Galileo instructions:
Only one binary blob is needed for Remote Management Unit (RMU) within Intel
Quark SoC. Not like FSP, U-Boot does not call into the binary. The binary is
needed by the Quark SoC itself.
You can get the binary blob from Quark Board Support Package from Intel website:
* ./QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
Rename the file and put it to the board directory by:
$ cp RMU.bin board/intel/galileo/rmu.bin
Now you can build U-Boot and obtain u-boot.rom
$ make galileo_defconfig
$ make all
Test with coreboot
------------------
For testing U-Boot as the coreboot payload, there are things that need be paid
@ -126,11 +172,21 @@ Make sure 0x1110000 matches CONFIG_SYS_TEXT_BASE and 0x1110015 matches the
symbol address of _start (in arch/x86/cpu/start.S).
If you want to use ELF as the coreboot payload, change U-Boot configuration to
use CONFIG_OF_EMBED.
use CONFIG_OF_EMBED instead of CONFIG_OF_SEPARATE.
To enable video you must enable these options in coreboot:
- Set framebuffer graphics resolution (1280x1024 32k-color (1:5:5))
- Keep VESA framebuffer
At present it seems that for Minnowboard Max, coreboot does not pass through
the video information correctly (it always says the resolution is 0x0). This
works correctly for link though.
CPU Microcode
-------------
Modern CPU usually requires a special bit stream called microcode [5] to be
Modern CPUs usually require a special bit stream called microcode [5] 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.
@ -162,6 +218,69 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
mode to use. U-Boot sets up some reasonable values but you can
adjust then with this command.
Development Flow
----------------
These notes are for those who want to port U-Boot to a new x86 platform.
Since x86 CPUs boot from SPI flash, a SPI flash emulator is a good investment.
The Dediprog em100 can be used on Linux. The em100 tool is available here:
http://review.coreboot.org/p/em100.git
On Minnowboard Max the following command line can be used:
sudo em100 -s -p LOW -d u-boot.rom -c W25Q64DW -r
A suitable clip for connecting over the SPI flash chip is here:
http://www.dediprog.com/pd/programmer-accessories/EM-TC-8
This allows you to override the SPI flash contents for development purposes.
Typically you can write to the em100 in around 1200ms, considerably faster
than programming the real flash device each time. The only important
limitation of the em100 is that it only supports SPI bus speeds up to 20MHz.
This means that images must be set to boot with that speed. This is an
Intel-specific feature - e.g. tools/ifttool has an option to set the SPI
speed in the SPI descriptor region.
If your chip/board uses an Intel Firmware Support Package (FSP) it is fairly
easy to fit it in. You can follow the Minnowboard Max implementation, for
example. Hopefully you will just need to create new files similar to those
in arch/x86/cpu/baytrail which provide Bay Trail support.
If you are not using an FSP you have more freedom and more responsibility.
The ivybridge support works this way, although it still uses a ROM for
graphics and still has binary blobs containing Intel code. You should aim to
support all important peripherals on your platform including video and storage.
Use the device tree for configuration where possible.
For the microcode you can create a suitable device tree file using the
microcode tool:
./tools/microcode-tool -d microcode.dat create <model>
or if you only have header files and not the full Intel microcode.dat database:
./tools/microcode-tool -H BAY_TRAIL_FSP_KIT/Microcode/M0130673322.h \
-H BAY_TRAIL_FSP_KIT/Microcode/M0130679901.h \
create all
These are written to arch/x86/dts/microcode/ by default.
Note that it is possible to just add the micrcode for your CPU if you know its
model. U-Boot prints this information when it starts
CPU: x86_64, vendor Intel, device 30673h
so here we can use the M0130673322 file.
If you platform can display POST codes on two little 7-segment displays on
the board, then you can use post_code() calls from C or assembler to monitor
boot progress. This can be good for debugging.
If not, you can try to get serial working as early as possible. The early
debug serial port may be useful here. See setup_early_uart() for an example.
TODO List
---------
- Audio

View File

@ -24,6 +24,7 @@ obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
obj-$(CONFIG_MXC_MMC) += mxcmmc.o
obj-$(CONFIG_MXS_MMC) += mxsmmc.o
obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
obj-$(CONFIG_X86) += pci_mmc.o
obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
obj-$(CONFIG_S3C_SDI) += s3c_sdi.o

42
drivers/mmc/pci_mmc.c Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2015, Google, Inc
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <malloc.h>
#include <sdhci.h>
#include <asm/pci.h>
int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
int num_ids)
{
struct sdhci_host *mmc_host;
pci_dev_t devbusfn;
u32 iobase;
int ret;
int i;
for (i = 0; i < num_ids; i++) {
devbusfn = pci_find_devices(mmc_supported, i);
if (devbusfn == -1)
return -ENODEV;
mmc_host = malloc(sizeof(struct sdhci_host));
if (!mmc_host)
return -ENOMEM;
mmc_host->name = (char *)name;
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
mmc_host->ioaddr = (void *)iobase;
mmc_host->quirks = 0;
ret = add_sdhci(mmc_host, 0, 0);
if (ret)
return ret;
}
return 0;
}

View File

@ -15,6 +15,7 @@
#include <common.h>
#include <command.h>
#include <errno.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <pci.h>
@ -236,6 +237,48 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
return -1;
}
pci_dev_t pci_find_class(uint find_class, int index)
{
int bus;
int devnum;
pci_dev_t bdf;
uint32_t class;
for (bus = 0; bus <= pci_last_busno(); bus++) {
for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
pci_read_config_dword(PCI_BDF(bus, devnum, 0),
PCI_CLASS_REVISION, &class);
if (class >> 16 == 0xffff)
continue;
for (bdf = PCI_BDF(bus, devnum, 0);
bdf <= PCI_BDF(bus, devnum,
PCI_MAX_PCI_FUNCTIONS - 1);
bdf += PCI_BDF(0, 0, 1)) {
pci_read_config_dword(bdf, PCI_CLASS_REVISION,
&class);
class >>= 8;
if (class != find_class)
continue;
/*
* Decrement the index. We want to return the
* correct device, so index is 0 for the first
* matching device, 1 for the second, etc.
*/
if (index) {
index--;
continue;
}
/* Return index'th controller. */
return bdf;
}
}
}
return -ENODEV;
}
pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
{
struct pci_device_id ids[2] = { {}, {0, 0} };

View File

@ -228,11 +228,12 @@ int vbe_get_video_info(struct graphic_device *gdev)
#endif
}
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
{
struct pci_rom_header *rom, *ram;
int vesa_mode = -1;
uint16_t class;
bool emulate;
int ret;
/* Only execute VGA ROMs */
@ -262,6 +263,29 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
#endif
debug("Selected vesa mode %#x\n", vesa_mode);
if (exec_method & PCI_ROM_USE_NATIVE) {
#ifdef CONFIG_X86
emulate = false;
#else
if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
printf("BIOS native execution is only available on x86\n");
return -ENOSYS;
}
emulate = true;
#endif
} else {
#ifdef CONFIG_BIOSEMU
emulate = true;
#else
if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
return -ENOSYS;
}
emulate = false;
#endif
}
if (emulate) {
#ifdef CONFIG_BIOSEMU
BE_VGAInfo *info;
@ -274,9 +298,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
vesa_mode, &mode_info);
if (ret)
return ret;
#else
printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
return -ENOSYS;
#endif
} else {
#ifdef CONFIG_X86
@ -284,9 +305,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
&mode_info);
#else
printf("BIOS native execution is only available on x86\n");
return -ENOSYS;
#endif
}
debug("Final vesa mode %#x\n", mode_info.video_mode);

View File

@ -7,6 +7,7 @@
*/
#include <common.h>
#include <errno.h>
#include <malloc.h>
#include <spi.h>
#include <pci.h>
@ -21,6 +22,7 @@
struct ich_ctlr {
pci_dev_t dev; /* PCI device number */
int ich_version; /* Controller version, 7 or 9 */
bool use_sbase; /* Use SBASE instead of RCB */
int ichspi_lock;
int locked;
uint8_t *opmenu;
@ -145,7 +147,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
* ICH 7 SPI controller only supports array read command
* and byte program command for SST flash
*/
if (ctlr.ich_version == 7) {
if (ctlr.ich_version == 7 || ctlr.use_sbase) {
ich->slave.op_mode_rx = SPI_OPM_RX_AS;
ich->slave.op_mode_tx = SPI_OPM_TX_BP;
}
@ -175,13 +177,15 @@ void spi_free_slave(struct spi_slave *slave)
static int get_ich_version(uint16_t device_id)
{
if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC ||
device_id == PCI_DEVICE_ID_INTEL_ITC_LPC)
device_id == PCI_DEVICE_ID_INTEL_ITC_LPC ||
device_id == PCI_DEVICE_ID_INTEL_QRK_ILB)
return 7;
if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
(device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX))
device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
return 9;
return 0;
@ -204,14 +208,14 @@ static int ich9_can_do_33mhz(pci_dev_t dev)
return speed == 1;
}
static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
static int ich_find_spi_controller(struct ich_ctlr *ich)
{
int last_bus = pci_last_busno();
int bus;
if (last_bus == -1) {
debug("No PCI busses?\n");
return -1;
return -ENODEV;
}
for (bus = 0; bus <= last_bus; bus++) {
@ -225,24 +229,33 @@ static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
device_id = ids >> 16;
if (vendor_id == PCI_VENDOR_ID_INTEL) {
*devp = dev;
*ich_versionp = get_ich_version(device_id);
return 0;
ich->dev = dev;
ich->ich_version = get_ich_version(device_id);
if (device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
ich->use_sbase = true;
return ich->ich_version == 0 ? -ENODEV : 0;
}
}
debug("ICH SPI: No ICH found.\n");
return -1;
return -ENODEV;
}
static int ich_init_controller(struct ich_ctlr *ctlr)
{
uint8_t *rcrb; /* Root Complex Register Block */
uint32_t rcba; /* Root Complex Base Address */
uint32_t sbase_addr;
uint8_t *sbase;
pci_read_config_dword(ctlr->dev, 0xf0, &rcba);
/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
rcrb = (uint8_t *)(rcba & 0xffffc000);
/* SBASE is similar */
pci_read_config_dword(ctlr->dev, 0x54, &sbase_addr);
sbase = (uint8_t *)(sbase_addr & 0xfffffe00);
if (ctlr->ich_version == 7) {
struct ich7_spi_regs *ich7_spi;
@ -262,7 +275,10 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
} else if (ctlr->ich_version == 9) {
struct ich9_spi_regs *ich9_spi;
ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
if (ctlr->use_sbase)
ich9_spi = (struct ich9_spi_regs *)sbase;
else
ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
ctlr->opmenu = ich9_spi->opmenu;
ctlr->menubytes = sizeof(ich9_spi->opmenu);
@ -282,12 +298,13 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
ctlr->ich_version);
return -1;
}
debug("ICH SPI: Version %d detected\n", ctlr->ich_version);
/* Work out the maximum speed we can support */
ctlr->max_speed = 20000000;
if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev))
ctlr->max_speed = 33000000;
debug("ICH SPI: Version %d detected at %p, speed %ld\n",
ctlr->ich_version, ctlr->base, ctlr->max_speed);
ich_set_bbar(ctlr, 0);
@ -298,7 +315,7 @@ void spi_init(void)
{
uint8_t bios_cntl;
if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) {
if (ich_find_spi_controller(&ctlr)) {
printf("ICH SPI: Cannot find device\n");
return;
}
@ -312,10 +329,20 @@ void spi_init(void)
* Disable the BIOS write protect so write commands are allowed. On
* v9, deassert SMM BIOS Write Protect Disable.
*/
pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
if (ctlr.ich_version == 9)
bios_cntl &= ~(1 << 5);
pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
if (ctlr.use_sbase) {
struct ich9_spi_regs *ich9_spi;
ich9_spi = (struct ich9_spi_regs *)ctlr.base;
bios_cntl = ich_readb(&ich9_spi->bcr);
bios_cntl &= ~(1 << 5); /* clear Enable InSMM_STS (EISS) */
bios_cntl |= 1; /* Write Protect Disable (WPD) */
ich_writeb(bios_cntl, &ich9_spi->bcr);
} else {
pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
if (ctlr.ich_version == 9)
bios_cntl &= ~(1 << 5);
pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
}
}
int spi_claim_bus(struct spi_slave *slave)

View File

@ -37,18 +37,19 @@ struct ich9_spi_regs {
uint8_t opmenu[8]; /* 0x98 */
uint32_t bbar;
uint8_t _reserved3[12];
uint32_t fdoc;
uint32_t fdoc; /* 0xb0 */
uint32_t fdod;
uint8_t _reserved4[8];
uint32_t afc;
uint32_t afc; /* 0xc0 */
uint32_t lvscc;
uint32_t uvscc;
uint8_t _reserved5[4];
uint32_t fpb;
uint32_t fpb; /* 0xd0 */
uint8_t _reserved6[28];
uint32_t srdl;
uint32_t srdl; /* 0xf0 */
uint32_t srdc;
uint32_t srd;
uint32_t scs;
uint32_t bcr;
} __packed;
enum {

View File

@ -47,6 +47,7 @@ obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
# designware
obj-$(CONFIG_USB_DWC2) += dwc2.o

View File

@ -34,57 +34,6 @@ static struct pci_device_id ehci_pci_ids[] = {
{0, 0}
};
#else
static pci_dev_t ehci_find_class(int index)
{
int bus;
int devnum;
pci_dev_t bdf;
uint32_t class;
for (bus = 0; bus <= pci_last_busno(); bus++) {
for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
pci_read_config_dword(PCI_BDF(bus, devnum, 0),
PCI_CLASS_REVISION, &class);
if (class >> 16 == 0xffff)
continue;
for (bdf = PCI_BDF(bus, devnum, 0);
bdf <= PCI_BDF(bus, devnum,
PCI_MAX_PCI_FUNCTIONS - 1);
bdf += PCI_BDF(0, 0, 1)) {
pci_read_config_dword(bdf, PCI_CLASS_REVISION,
&class);
class >>= 8;
/*
* Here be dragons! In case we have multiple
* PCI EHCI controllers, this function will
* be called multiple times as well. This
* function will scan the PCI busses, always
* starting from bus 0, device 0, function 0,
* until it finds an USB controller. The USB
* stack gives us an 'index' of a controller
* that is currently being registered, which
* is a number, starting from 0 and growing
* in ascending order as controllers are added.
* To avoid probing the same controller in tne
* subsequent runs of this function, we will
* skip 'index - 1' detected controllers and
* report the index'th controller.
*/
if (class != PCI_CLASS_SERIAL_USB_EHCI)
continue;
if (index) {
index--;
continue;
}
/* Return index'th controller. */
return bdf;
}
}
}
return -ENODEV;
}
#endif
/*
@ -102,7 +51,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
#ifdef CONFIG_PCI_EHCI_DEVICE
pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
#else
pdev = ehci_find_class(index);
pdev = pci_find_class(PCI_CLASS_SERIAL_USB_EHCI, index);
#endif
if (pdev < 0) {
printf("EHCI host controller not found\n");

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, Google, Inc
* Written by Simon Glass <sjg@chromium.org>
* All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <errno.h>
#include <pci.h>
#include <usb.h>
#include "xhci.h"
/*
* Create the appropriate control structures to manage a new XHCI host
* controller.
*/
int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
struct xhci_hcor **ret_hcor)
{
struct xhci_hccr *hccr;
struct xhci_hcor *hcor;
pci_dev_t pdev;
uint32_t cmd;
int len;
pdev = pci_find_class(PCI_CLASS_SERIAL_USB_XHCI, index);
if (pdev < 0) {
printf("XHCI host controller not found\n");
return -1;
}
hccr = (struct xhci_hccr *)pci_map_bar(pdev,
PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
len = HC_LENGTH(xhci_readl(&hccr->cr_capbase));
hcor = (struct xhci_hcor *)((uint32_t)hccr + len);
debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
(uint32_t)hccr, (uint32_t)hcor, len);
*ret_hccr = hccr;
*ret_hcor = hcor;
/* enable busmaster */
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER;
pci_write_config_dword(pdev, PCI_COMMAND, cmd);
return 0;
}
/*
* Destroy the appropriate control structures corresponding * to the XHCI host
* controller
*/
void xhci_hcd_stop(int index)
{
}

View File

@ -23,6 +23,7 @@ struct pci_device_id vesa_video_ids[] = {
{ .vendor = 0x1002, .device = 0x5159 },
{ .vendor = 0x1002, .device = 0x4752 },
{ .vendor = 0x1002, .device = 0x5452 },
{ .vendor = 0x8086, .device = 0x0f31 },
{},
};
@ -41,8 +42,10 @@ void *video_hw_init(void)
printf("no card detected\n");
return NULL;
}
printf("bdf %x\n", dev);
ret = pci_run_vga_bios(dev, NULL, true);
bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
ret = pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE |
PCI_ROM_ALLOW_FALLBACK);
bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
if (ret) {
printf("failed to run video BIOS: %d\n", ret);
return NULL;
@ -58,7 +61,7 @@ void *video_hw_init(void)
sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
bits_per_pixel);
printf("%s\n", gdev->modeIdent);
debug("Framex buffer at %x\n", gdev->pciBase);
debug("Frame buffer at %x\n", gdev->pciBase);
return (void *)gdev;
}

View File

@ -86,9 +86,9 @@ enum bootstage_id {
BOOTSTAGE_ID_POST_FAIL_R, /* Post failure reported after reloc */
/*
* This set is reported ony by x86, and the meaning is different. In
* This set is reported only by x86, and the meaning is different. In
* this case we are reporting completion of a particular stage.
* This should probably change in he x86 code (which doesn't report
* This should probably change in the x86 code (which doesn't report
* errors in any case), but discussion this can perhaps wait until we
* have a generic board implementation.
*/
@ -194,6 +194,7 @@ enum bootstage_id {
BOOTSTAGE_ID_MAIN_CPU_READY,
BOOTSTAGE_ID_ACCUM_LCD,
BOOTSTAGE_ID_ACCUM_SCSI,
/* a few spare for the user, from here */
BOOTSTAGE_ID_USER,

60
include/configs/galileo.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* board/config.h - configuration options, board specific
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <configs/x86-common.h>
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_X86_SERIAL
/* ns16550 UART is memory-mapped in Quark SoC */
#undef CONFIG_SYS_NS16550_PORT_MAPPED
#define CONFIG_PCI_MEM_BUS 0x90000000
#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
#define CONFIG_PCI_MEM_SIZE 0x20000000
#define CONFIG_PCI_PREF_BUS 0xb0000000
#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS
#define CONFIG_PCI_PREF_SIZE 0x20000000
#define CONFIG_PCI_IO_BUS 0x2000
#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial\0" \
"stdout=serial\0" \
"stderr=serial\0"
/* SATA is not supported in Quark SoC */
#undef CONFIG_SCSI_AHCI
#undef CONFIG_CMD_SCSI
/* Video is not supported in Quark SoC */
#undef CONFIG_VIDEO
#undef CONFIG_CFB_CONSOLE
/* SD/MMC support */
#define CONFIG_MMC
#define CONFIG_SDHCI
#define CONFIG_GENERIC_MMC
#define CONFIG_MMC_SDMA
#define CONFIG_CMD_MMC
#endif /* __CONFIG_H */

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* board/config.h - configuration options, board specific
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <configs/x86-common.h>
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_X86_SERIAL
#define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0xd0000000
#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
#define CONFIG_PCI_MEM_SIZE 0x10000000
#define CONFIG_PCI_PREF_BUS 0xc0000000
#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS
#define CONFIG_PCI_PREF_SIZE 0x10000000
#define CONFIG_PCI_IO_BUS 0x2000
#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
#define CONFIG_RTL8169
#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \
"stdout=vga,serial\0" \
"stderr=vga,serial\0"
#define CONFIG_SCSI_DEV_LIST \
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}
#define CONFIG_SPI_FLASH_SST
#define CONFIG_MMC
#define CONFIG_SDHCI
#define CONFIG_GENERIC_MMC
#define CONFIG_MMC_SDMA
#define CONFIG_CMD_MMC
#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
#ifndef CONFIG_SYS_COREBOOT
#define CONFIG_VIDEO_VESA
#endif
#define VIDEO_IO_OFFSET 0
#define CONFIG_X86EMU_RAW_IO
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_FIT_SIGNATURE
#define CONFIG_RSA
/* Avoid a warning in the Realtek Ethernet driver */
#define CONFIG_SYS_CACHELINE_SIZE 16
#endif /* __CONFIG_H */

View File

@ -39,7 +39,6 @@
/* SATA AHCI storage */
#define CONFIG_SCSI_AHCI
#define CONFIG_SATA_INTEL
#ifdef CONFIG_SCSI_AHCI
#define CONFIG_LIBATA
#define CONFIG_SYS_64BIT_LBA
@ -245,6 +244,9 @@
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
#define CONFIG_BOOTSTAGE
#define CONFIG_CMD_BOOTSTAGE
#define CONFIG_CMD_USB
#define CONFIG_EXTRA_ENV_SETTINGS \

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*
* Intel Quark MRC bindings include several properties
* as part of an Intel Quark MRC node. In most cases,
* the value of these properties uses the standard values
* defined in this header.
*/
#ifndef _DT_BINDINGS_QRK_MRC_H_
#define _DT_BINDINGS_QRK_MRC_H_
/* MRC platform data flags */
#define MRC_FLAG_ECC_EN 0x00000001
#define MRC_FLAG_SCRAMBLE_EN 0x00000002
#define MRC_FLAG_MEMTEST_EN 0x00000004
/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
#define MRC_FLAG_TOP_TREE_EN 0x00000008
/* If set ODR signal is asserted to DRAM devices on writes */
#define MRC_FLAG_WR_ODT_EN 0x00000010
/* DRAM width */
#define DRAM_WIDTH_X8 0
#define DRAM_WIDTH_X16 1
#define DRAM_WIDTH_X32 2
/* DRAM speed */
#define DRAM_FREQ_800 0
#define DRAM_FREQ_1066 1
/* DRAM type */
#define DRAM_TYPE_DDR3 0
#define DRAM_TYPE_DDR3L 1
/* DRAM rank mask */
#define DRAM_RANK(n) (1 << (n))
/* DRAM channel mask */
#define DRAM_CHANNEL(n) (1 << (n))
/* DRAM channel width */
#define DRAM_CHANNEL_WIDTH_X8 0
#define DRAM_CHANNEL_WIDTH_X16 1
#define DRAM_CHANNEL_WIDTH_X32 2
/* DRAM address mode */
#define DRAM_ADDR_MODE0 0
#define DRAM_ADDR_MODE1 1
#define DRAM_ADDR_MODE2 2
/* DRAM refresh rate */
#define DRAM_REFRESH_RATE_195US 1
#define DRAM_REFRESH_RATE_39US 2
#define DRAM_REFRESH_RATE_785US 3
/* DRAM SR temprature range */
#define DRAM_SRT_RANGE_NORMAL 0
#define DRAM_SRT_RANGE_EXTENDED 1
/* DRAM ron value */
#define DRAM_RON_34OHM 0
#define DRAM_RON_40OHM 1
/* DRAM rtt nom value */
#define DRAM_RTT_NOM_40OHM 0
#define DRAM_RTT_NOM_60OHM 1
#define DRAM_RTT_NOM_120OHM 2
/* DRAM rd odt value */
#define DRAM_RD_ODT_OFF 0
#define DRAM_RD_ODT_60OHM 1
#define DRAM_RD_ODT_120OHM 2
#define DRAM_RD_ODT_180OHM 3
/* DRAM density */
#define DRAM_DENSITY_512M 0
#define DRAM_DENSITY_1G 1
#define DRAM_DENSITY_2G 2
#define DRAM_DENSITY_4G 3
#endif /* _DT_BINDINGS_QRK_MRC_H_ */

View File

@ -167,6 +167,7 @@ enum fdt_compat_id {
COMPAT_INTEL_GMA, /* Intel Graphics Media Accelerator */
COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */
COMPAT_INTEL_ICH_SPI, /* Intel ICH7/9 SPI controller */
COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */
COMPAT_COUNT,
};

View File

@ -438,6 +438,20 @@ int board_mmc_init(bd_t *bis);
int cpu_mmc_init(bd_t *bis);
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
struct pci_device_id;
/**
* pci_mmc_init() - set up PCI MMC devices
*
* This finds all the matching PCI IDs and sets them up as MMC devices.
*
* @name: Name to use for devices
* @mmc_supported: PCI IDs to search for
* @num_ids: Number of elements in @mmc_supported
*/
int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
int num_ids);
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535

View File

@ -644,8 +644,7 @@ extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index);
extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
extern pci_dev_t pci_find_class(int wanted_class, int wanted_sub_code,
int wanted_prog_if, int index);
pci_dev_t pci_find_class(unsigned int find_class, int index);
extern int pci_hose_config_device(struct pci_controller *hose,
pci_dev_t dev,

View File

@ -1346,6 +1346,7 @@
#define PCI_VENDOR_ID_REALTEK 0x10ec
#define PCI_DEVICE_ID_REALTEK_8139 0x8139
#define PCI_DEVICE_ID_REALTEK_8168 0x8168
#define PCI_VENDOR_ID_XILINX 0x10ee
#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0
@ -2591,9 +2592,17 @@
#define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823
#define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824
#define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F
#define PCI_DEVICE_ID_INTEL_QRK_SDIO 0x08A7
#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936
#define PCI_DEVICE_ID_INTEL_QRK_EMAC 0x0937
#define PCI_DEVICE_ID_INTEL_QRK_ILB 0x095E
#define PCI_DEVICE_ID_INTEL_I960 0x0960
#define PCI_DEVICE_ID_INTEL_I960RM 0x0962
#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO 0x0f15
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD 0x0f16
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC 0x0f1c
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA 0x0f23
#define PCI_DEVICE_ID_INTEL_82541ER 0x1078
#define PCI_DEVICE_ID_INTEL_82541GI_LF 0x107c
#define PCI_DEVICE_ID_INTEL_82542 0x1000

View File

@ -33,14 +33,25 @@ struct pci_rom_data {
uint16_t reserved_2;
};
/*
* Determines which execution method is used and whether we allow falling back
* to the other if the requested method is not available.
*/
enum pci_rom_emul {
PCI_ROM_EMULATE = 0 << 0,
PCI_ROM_USE_NATIVE = 1 << 0,
PCI_ROM_ALLOW_FALLBACK = 1 << 1,
};
/**
* pci_run_vga_bios() - Run the VGA BIOS in an x86 PC
*
* @dev: Video device containing the BIOS
* @int15_handler: Function to call to handle int 0x15
* @emulate: true to use the x86 emulator, false to run native
* @exec_method: flags from enum pci_rom_emul
*/
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate);
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void),
int exec_method);
/**
* board_map_oprom_vendev() - map several PCI IDs to the one the ROM expects

Some files were not shown because too many files have changed in this diff Show More