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:
121
u-boot/arch/x86/cpu/quark/Kconfig
Normal file
121
u-boot/arch/x86/cpu/quark/Kconfig
Normal 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
|
||||
9
u-boot/arch/x86/cpu/quark/Makefile
Normal file
9
u-boot/arch/x86/cpu/quark/Makefile
Normal 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
|
||||
163
u-boot/arch/x86/cpu/quark/acpi.c
Normal file
163
u-boot/arch/x86/cpu/quark/acpi.c
Normal 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;
|
||||
}
|
||||
105
u-boot/arch/x86/cpu/quark/car.S
Normal file
105
u-boot/arch/x86/cpu/quark/car.S
Normal 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
|
||||
182
u-boot/arch/x86/cpu/quark/dram.c
Normal file
182
u-boot/arch/x86/cpu/quark/dram.c
Normal 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;
|
||||
}
|
||||
396
u-boot/arch/x86/cpu/quark/hte.c
Normal file
396
u-boot/arch/x86/cpu/quark/hte.c
Normal 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();
|
||||
}
|
||||
44
u-boot/arch/x86/cpu/quark/hte.h
Normal file
44
u-boot/arch/x86/cpu/quark/hte.h
Normal 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_ */
|
||||
49
u-boot/arch/x86/cpu/quark/irq.c
Normal file
49
u-boot/arch/x86/cpu/quark/irq.c
Normal 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,
|
||||
};
|
||||
205
u-boot/arch/x86/cpu/quark/mrc.c
Normal file
205
u-boot/arch/x86/cpu/quark/mrc.c
Normal 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();
|
||||
}
|
||||
1472
u-boot/arch/x86/cpu/quark/mrc_util.c
Normal file
1472
u-boot/arch/x86/cpu/quark/mrc_util.c
Normal file
File diff suppressed because it is too large
Load Diff
119
u-boot/arch/x86/cpu/quark/mrc_util.h
Normal file
119
u-boot/arch/x86/cpu/quark/mrc_util.h
Normal 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_ */
|
||||
77
u-boot/arch/x86/cpu/quark/msg_port.c
Normal file
77
u-boot/arch/x86/cpu/quark/msg_port.c
Normal 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);
|
||||
}
|
||||
366
u-boot/arch/x86/cpu/quark/quark.c
Normal file
366
u-boot/arch/x86/cpu/quark/quark.c
Normal 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;
|
||||
}
|
||||
2621
u-boot/arch/x86/cpu/quark/smc.c
Normal file
2621
u-boot/arch/x86/cpu/quark/smc.c
Normal file
File diff suppressed because it is too large
Load Diff
533
u-boot/arch/x86/cpu/quark/smc.h
Normal file
533
u-boot/arch/x86/cpu/quark/smc.h
Normal 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_ */
|
||||
Reference in New Issue
Block a user