avionic design with actual uboot and tooling

submodule of avionic design uboot bootloader and with included tools to
get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
2026-03-03 21:46:32 +02:00
parent fe3ba02c96
commit 68d74d3181
11967 changed files with 2221897 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
config INTEL_QUARK
bool
select HAVE_RMU
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.
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 irq.o msg_port.o quark.o
obj-y += mrc.o mrc_util.o hte.o smc.o
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/acpi_table.h>
#include <asm/ioapic.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
#include <asm/arch/iomap.h>
void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
void *dsdt)
{
struct acpi_table_header *header = &(fadt->header);
u16 pmbase = ACPI_PM1_BASE_ADDRESS;
memset((void *)fadt, 0, sizeof(struct acpi_fadt));
acpi_fill_header(header, "FACP");
header->length = sizeof(struct acpi_fadt);
header->revision = 4;
fadt->firmware_ctrl = (u32)facs;
fadt->dsdt = (u32)dsdt;
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
fadt->sci_int = 9;
fadt->smi_cmd = 0;
fadt->acpi_enable = 0;
fadt->acpi_disable = 0;
fadt->s4bios_req = 0;
fadt->pstate_cnt = 0;
fadt->pm1a_evt_blk = pmbase;
fadt->pm1b_evt_blk = 0x0;
fadt->pm1a_cnt_blk = pmbase + 0x4;
fadt->pm1b_cnt_blk = 0x0;
fadt->pm2_cnt_blk = 0x0;
fadt->pm_tmr_blk = pmbase + 0x8;
fadt->gpe0_blk = ACPI_GPE0_BASE_ADDRESS;
fadt->gpe1_blk = 0;
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm2_cnt_len = 0;
fadt->pm_tmr_len = 4;
fadt->gpe0_blk_len = 8;
fadt->gpe1_blk_len = 0;
fadt->gpe1_base = 0;
fadt->cst_cnt = 0;
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
fadt->flush_size = 0;
fadt->flush_stride = 0;
fadt->duty_offset = 1;
fadt->duty_width = 3;
fadt->day_alrm = 0x00;
fadt->mon_alrm = 0x00;
fadt->century = 0x00;
fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES;
fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_RESET_REGISTER |
ACPI_FADT_PLATFORM_CLOCK;
fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->reset_reg.bit_width = 8;
fadt->reset_reg.bit_offset = 0;
fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
fadt->reset_reg.addrl = IO_PORT_RESET;
fadt->reset_reg.addrh = 0;
fadt->reset_value = SYS_RST | RST_CPU;
fadt->x_firmware_ctl_l = (u32)facs;
fadt->x_firmware_ctl_h = 0;
fadt->x_dsdt_l = (u32)dsdt;
fadt->x_dsdt_h = 0;
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
fadt->x_pm1a_evt_blk.bit_offset = 0;
fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
fadt->x_pm1a_evt_blk.addrh = 0x0;
fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1b_evt_blk.bit_width = 0;
fadt->x_pm1b_evt_blk.bit_offset = 0;
fadt->x_pm1b_evt_blk.access_size = 0;
fadt->x_pm1b_evt_blk.addrl = 0x0;
fadt->x_pm1b_evt_blk.addrh = 0x0;
fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
fadt->x_pm1a_cnt_blk.bit_offset = 0;
fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
fadt->x_pm1a_cnt_blk.addrh = 0x0;
fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1b_cnt_blk.bit_width = 0;
fadt->x_pm1b_cnt_blk.bit_offset = 0;
fadt->x_pm1b_cnt_blk.access_size = 0;
fadt->x_pm1b_cnt_blk.addrl = 0x0;
fadt->x_pm1b_cnt_blk.addrh = 0x0;
fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
fadt->x_pm2_cnt_blk.bit_offset = 0;
fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
fadt->x_pm2_cnt_blk.addrh = 0x0;
fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
fadt->x_gpe0_blk.addrh = 0x0;
fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_gpe1_blk.bit_width = 0;
fadt->x_gpe1_blk.bit_offset = 0;
fadt->x_gpe1_blk.access_size = 0;
fadt->x_gpe1_blk.addrl = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
header->checksum = table_compute_checksum(fadt, header->length);
}
static int acpi_create_madt_irq_overrides(u32 current)
{
struct acpi_madt_irqoverride *irqovr;
u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
int length = 0;
irqovr = (void *)current;
length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
irqovr = (void *)(current + length);
length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
return length;
}
u32 acpi_fill_madt(u32 current)
{
current += acpi_create_madt_lapics(current);
current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
current += acpi_create_madt_irq_overrides(current);
return current;
}

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

View File

@@ -0,0 +1,182 @@
/*
* 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 <malloc.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/arch/mrc.h>
#include <asm/arch/msg_port.h>
#include <asm/arch/quark.h>
DECLARE_GLOBAL_DATA_PTR;
static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
if (ret)
return ret;
cache = mrccache_find_current(&entry);
if (!cache)
return -ENOENT;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
/* copy mrc cache to the mrc_params */
memcpy(&mrc_params->timings, cache->data, cache->data_size);
return 0;
}
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;
}
#ifdef CONFIG_ENABLE_MRC_CACHE
mrc_params->boot_mode = prepare_mrc_cache(mrc_params);
if (mrc_params->boot_mode)
mrc_params->boot_mode = BM_COLD;
else
mrc_params->boot_mode = BM_FAST;
#else
mrc_params->boot_mode = BM_COLD;
#endif
/*
* 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;
#ifdef CONFIG_ENABLE_MRC_CACHE
char *cache;
#endif
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);
/* variable range MTRR#2: RAM area */
disable_caches();
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_RAM),
0 | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_RAM),
(~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID);
enable_caches();
#ifdef CONFIG_ENABLE_MRC_CACHE
cache = malloc(sizeof(struct mrc_timings));
if (cache) {
memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
gd->arch.mrc_output = cache;
gd->arch.mrc_output_len = sizeof(struct mrc_timings);
}
#endif
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;
}

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) & (1 << 30)) != 0);
tmp = msg_port_read(HTE, 0x00020011);
tmp |= (1 << 9);
tmp &= ~((1 << 12) | (1 << 13));
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 |= (1 << 8);
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 | (1 << 8));
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();
}

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_ */

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <asm/irq.h>
#include <asm/arch/device.h>
#include <asm/arch/quark.h>
int quark_irq_router_probe(struct udevice *dev)
{
struct quark_rcba *rcba;
u32 base;
qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
base &= ~MEM_BAR_EN;
rcba = (struct quark_rcba *)base;
/*
* Route Quark PCI device interrupt pin to PIRQ
*
* Route device#23's INTA/B/C/D to PIRQA/B/C/D
* Route device#20,21's INTA/B/C/D to PIRQE/F/G/H
*/
writew(PIRQC, &rcba->rmu_ir);
writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12),
&rcba->d23_ir);
writew(PIRQD, &rcba->core_ir);
writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12),
&rcba->d20d21_ir);
return irq_router_common_init(dev);
}
static const struct udevice_id quark_irq_router_ids[] = {
{ .compatible = "intel,quark-irq-router" },
{ }
};
U_BOOT_DRIVER(quark_irq_router_drv) = {
.name = "quark_intel_irq",
.id = UCLASS_IRQ,
.of_match = quark_irq_router_ids,
.probe = quark_irq_router_probe,
};

View File

@@ -0,0 +1,205 @@
/*
* 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 <version.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,
U_BOOT_DATE, U_BOOT_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,119 @@
/*
* 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__)
/* 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 <asm/arch/device.h>
#include <asm/arch/msg_port.h>
#include <asm/arch/quark.h>
void msg_port_setup(int op, int port, int reg)
{
qrk_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;
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_READ, port, reg);
qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_write(u8 port, u32 reg, u32 value)
{
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
qrk_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;
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_ALT_READ, port, reg);
qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_alt_write(u8 port, u32 reg, u32 value)
{
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
qrk_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;
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_READ, port, reg);
qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_io_write(u8 port, u32 reg, u32 value)
{
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_WRITE, port, reg);
}

View File

@@ -0,0 +1,366 @@
/*
* 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/ioapic.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/post.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 },
{},
};
static void quark_setup_mtrr(void)
{
u32 base, mask;
int i;
disable_caches();
/* mark the VGA RAM area as uncacheable */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_A0000,
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_B0000,
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
/* mark other fixed range areas as cacheable */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_00000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_40000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_80000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_90000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
for (i = MTRR_FIX_4K_C0000; i <= MTRR_FIX_4K_FC000; i++)
msg_port_write(MSG_PORT_HOST_BRIDGE, i,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
/* variable range MTRR#0: ROM area */
mask = ~(CONFIG_SYS_MONITOR_LEN - 1);
base = CONFIG_SYS_TEXT_BASE & mask;
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ROM),
base | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ROM),
mask | MTRR_PHYS_MASK_VALID);
/* variable range MTRR#1: eSRAM area */
mask = ~(ESRAM_SIZE - 1);
base = CONFIG_ESRAM_BASE & mask;
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ESRAM),
base | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ESRAM),
mask | MTRR_PHYS_MASK_VALID);
/* enable both variable and fixed range MTRRs */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_DEF_TYPE,
MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN);
enable_caches();
}
static void quark_setup_bars(void)
{
/* GPIO - D31:F0:R44h */
qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
CONFIG_GPIO_BASE | IO_BAR_EN);
/* ACPI PM1 Block - D31:F0:R48h */
qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
/* GPE0 - D31:F0:R4Ch */
qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
/* WDT - D31:F0:R84h */
qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
CONFIG_WDT_BASE | IO_BAR_EN);
/* RCBA - D31:F0:RF0h */
qrk_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);
}
static void quark_pcie_early_init(void)
{
/*
* Step1: Assert PCIe signal PERST#
*
* The CPU interface to the PERST# signal is platform dependent.
* Call the board-specific codes to perform this task.
*/
board_assert_perst();
/* Step2: PHY common lane reset */
msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_PHY_LANE_RST);
/* wait 1 ms for PHY common lane reset */
mdelay(1);
/* Step3: PHY sideband interface reset and controller main reset */
msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG,
PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST);
/* wait 80ms for PLL to lock */
mdelay(80);
/* Step4: Controller sideband interface reset */
msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_SB_RST);
/* wait 20ms for controller sideband interface reset */
mdelay(20);
/* Step5: De-assert PERST# */
board_deassert_perst();
/* Step6: Controller primary interface reset */
msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_PRI_RST);
/* Mixer Load Lane 0 */
msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0,
(1 << 6) | (1 << 7));
/* Mixer Load Lane 1 */
msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1,
(1 << 6) | (1 << 7));
}
static void quark_usb_early_init(void)
{
/* The sequence below comes from Quark firmware writer guide */
msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT,
1 << 1, (1 << 6) | (1 << 7));
msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_COMPBG,
(1 << 8) | (1 << 9), (1 << 7) | (1 << 10));
msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL1, 1 << 1);
msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_PLL1,
(1 << 3) | (1 << 4) | (1 << 5), 1 << 6);
msg_port_alt_clrbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 24);
}
static void quark_thermal_early_init(void)
{
/* The sequence below comes from Quark firmware writer guide */
/* thermal sensor mode config */
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1,
(1 << 3) | (1 << 4) | (1 << 5), 1 << 5);
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1,
(1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) |
(1 << 12), 1 << 9);
msg_port_alt_setbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 14);
msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 17);
msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 18);
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG2, 0xffff, 0x011f);
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff, 0x17);
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3,
(1 << 8) | (1 << 9), 1 << 8);
msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff000000);
msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG4,
0x7ff800, 0xc8 << 11);
/* thermal monitor catastrophic trip set point (105 celsius) */
msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff, 155);
/* thermal monitor catastrophic trip clear point (0 celsius) */
msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff0000, 50 << 16);
/* take thermal sensor out of reset */
msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG4, 1 << 0);
/* enable thermal monitor */
msg_port_setbits(MSG_PORT_RMU, TS_MODE, 1 << 15);
/* lock all thermal configuration */
msg_port_setbits(MSG_PORT_RMU, RMU_CTRL, (1 << 5) | (1 << 6));
}
static void quark_enable_legacy_seg(void)
{
msg_port_setbits(MSG_PORT_HOST_BRIDGE, HMISC2,
HMISC2_SEGE | HMISC2_SEGF | HMISC2_SEGAB);
}
int arch_cpu_init(void)
{
int ret;
post_code(POST_CPU_INIT);
ret = x86_cpu_init_f();
if (ret)
return ret;
/*
* Quark SoC does not support MSR MTRRs. Fixed and variable range MTRRs
* are accessed indirectly via the message port and not the traditional
* MSR mechanism. Only UC, WT and WB cache types are supported.
*/
quark_setup_mtrr();
/*
* Quark SoC has some non-standard BARs (excluding PCI standard BARs)
* which need be initialized with suggested values
*/
quark_setup_bars();
/* Initialize USB2 PHY */
quark_usb_early_init();
/* Initialize thermal sensor */
quark_thermal_early_init();
/* Turn on legacy segments (A/B/E/F) decode to system RAM */
quark_enable_legacy_seg();
return 0;
}
int arch_cpu_init_dm(void)
{
/*
* Initialize PCIe controller
*
* Quark SoC holds the PCIe controller in reset following a power on.
* U-Boot needs to release the PCIe controller from reset. The PCIe
* controller (D23:F0/F1) will not be visible in PCI configuration
* space and any access to its PCI configuration registers will cause
* system hang while it is held in reset.
*/
quark_pcie_early_init();
return 0;
}
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
void reset_cpu(ulong addr)
{
/* cold reset */
x86_full_reset();
}
static void quark_pcie_init(void)
{
u32 val;
/* PCIe upstream non-posted & posted request size */
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_CCFG,
CCFG_UPRS | CCFG_UNRS);
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_CCFG,
CCFG_UPRS | CCFG_UNRS);
/* PCIe packet fast transmit mode (IPF) */
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MPC2, MPC2_IPF);
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MPC2, MPC2_IPF);
/* PCIe message bus idle counter (SBIC) */
qrk_pci_read_config_dword(QUARK_PCIE0, PCIE_RP_MBC, &val);
val |= MBC_SBIC;
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MBC, val);
qrk_pci_read_config_dword(QUARK_PCIE1, PCIE_RP_MBC, &val);
val |= MBC_SBIC;
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MBC, val);
}
static void quark_usb_init(void)
{
u32 bar;
/* Change USB EHCI packet buffer OUT/IN threshold */
qrk_pci_read_config_dword(QUARK_USB_EHCI, PCI_BASE_ADDRESS_0, &bar);
writel((0x7f << 16) | 0x7f, bar + EHCI_INSNREG01);
/* Disable USB device interrupts */
qrk_pci_read_config_dword(QUARK_USB_DEVICE, PCI_BASE_ADDRESS_0, &bar);
writel(0x7f, bar + USBD_INT_MASK);
writel((0xf << 16) | 0xf, bar + USBD_EP_INT_MASK);
writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS);
}
int arch_early_init_r(void)
{
quark_pcie_init();
quark_usb_init();
return 0;
}
int cpu_mmc_init(bd_t *bis)
{
return pci_mmc_init("Quark SDHCI", mmc_supported);
}
int arch_misc_init(void)
{
#ifdef CONFIG_ENABLE_MRC_CACHE
/*
* We intend not to check any return value here, as even MRC cache
* is not saved successfully, it is not a severe error that will
* prevent system from continuing to boot.
*/
mrccache_save();
#endif
/* Assign a unique I/O APIC ID */
io_apic_set_id(1);
return 0;
}
void board_final_cleanup(void)
{
struct quark_rcba *rcba;
u32 base, val;
qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
base &= ~MEM_BAR_EN;
rcba = (struct quark_rcba *)base;
/* Initialize 'Component ID' to zero */
val = readl(&rcba->esd);
val &= ~0xff0000;
writel(val, &rcba->esd);
/* Lock HMBOUND for security */
msg_port_setbits(MSG_PORT_HOST_BRIDGE, HM_BOUND, HM_BOUND_LOCK);
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,533 @@
/*
* 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
/* DRP register defines */
#define DRP_RKEN0 (1 << 0)
#define DRP_RKEN1 (1 << 1)
#define DRP_PRI64BSPLITEN (1 << 13)
#define DRP_ADDRMAP_MAP0 (1 << 14)
#define DRP_ADDRMAP_MAP1 (1 << 15)
#define DRP_ADDRMAP_MASK 0x0000c000
/* DTR0 register defines */
#define DTR0_DFREQ_MASK 0x00000003
#define DTR0_TRP_MASK 0x000000f0
#define DTR0_TRCD_MASK 0x00000f00
#define DTR0_TCL_MASK 0x00007000
/* DTR1 register defines */
#define DTR1_TWCL_MASK 0x00000007
#define DTR1_TCMD_MASK 0x00000030
#define DTR1_TWTP_MASK 0x00000f00
#define DTR1_TCCD_12CLK (1 << 12)
#define DTR1_TCCD_18CLK (1 << 13)
#define DTR1_TCCD_MASK 0x00003000
#define DTR1_TFAW_MASK 0x000f0000
#define DTR1_TRAS_MASK 0x00f00000
#define DTR1_TRRD_MASK 0x03000000
#define DTR1_TRTP_MASK 0x70000000
/* DTR2 register defines */
#define DTR2_TRRDR_MASK 0x00000007
#define DTR2_TWWDR_MASK 0x00000700
#define DTR2_TRWDR_MASK 0x000f0000
/* DTR3 register defines */
#define DTR3_TWRDR_MASK 0x00000007
#define DTR3_TXXXX_MASK 0x00000070
#define DTR3_TRWSR_MASK 0x00000f00
#define DTR3_TWRSR_MASK 0x0001e000
#define DTR3_TXP_MASK 0x00c00000
/* DTR4 register defines */
#define DTR4_WRODTSTRT_MASK 0x00000003
#define DTR4_WRODTSTOP_MASK 0x00000070
#define DTR4_XXXX1_MASK 0x00000700
#define DTR4_XXXX2_MASK 0x00007000
#define DTR4_ODTDIS (1 << 15)
#define DTR4_TRGSTRDIS (1 << 16)
/* DPMC0 register defines */
#define DPMC0_PCLSTO_MASK 0x00070000
#define DPMC0_PREAPWDEN (1 << 21)
#define DPMC0_DYNSREN (1 << 23)
#define DPMC0_CLKGTDIS (1 << 24)
#define DPMC0_DISPWRDN (1 << 25)
#define DPMC0_ENPHYCLKGATE (1 << 29)
/* DRFC register defines */
#define DRFC_TREFI_MASK 0x00007000
#define DRFC_REFDBTCLR (1 << 21)
/* DSCH register defines */
#define DSCH_OOODIS (1 << 8)
#define DSCH_OOOST3DIS (1 << 9)
#define DSCH_NEWBYPDIS (1 << 12)
/* DCAL register defines */
#define DCAL_ZQCINT_MASK 0x00000700
#define DCAL_SRXZQCL_MASK 0x00003000
/* DRMC register defines */
#define DRMC_CKEMODE (1 << 4)
#define DRMC_ODTMODE (1 << 12)
#define DRMC_COLDWAKE (1 << 16)
/* PMSTS register defines */
#define PMSTS_DISR (1 << 0)
/* DCO register defines */
#define DCO_DRPLOCK (1 << 0)
#define DCO_CPGCLOCK (1 << 8)
#define DCO_PMICTL (1 << 28)
#define DCO_PMIDIS (1 << 29)
#define DCO_IC (1 << 31)
/* DECCCTRL register defines */
#define DECCCTRL_SBEEN (1 << 0)
#define DECCCTRL_DBEEN (1 << 1)
#define DECCCTRL_ENCBGEN (1 << 17)
/* 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) | (0x400 << 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) | (0x400 << 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_ */