mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
The U_BOOT_DRIVER macro creates a list of drivers used at link time, and all entries here must be unique. This in turn means that all entries in the code should also be unique in order to not lead to build failures later with unexpected build combinations. Typically, the problem we have here is when a driver is obviously based on another driver and didn't update this particular field and so while the name field reflects something unique the linker entry itself is not. In a few places this provides a more suitable string name as well, however. Reviewed-by: Marek Vasut <marek.vasut+usb@mailbox.org> Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com> # Tegra Reviewed-by: Peter Robinson <pbrobinson@gmail.com> Reviewed-by: Heiko Schocher <hs@nabladev.com> Reviewed-by: Simon Glass <sjg@chromium.org> Signed-off-by: Tom Rini <trini@konsulko.com>
213 lines
4.9 KiB
C
213 lines
4.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2016 Google, Inc
|
|
*
|
|
* From coreboot src/soc/intel/broadwell/romstage/raminit.c
|
|
*/
|
|
|
|
#define LOG_CATEGORY UCLASS_RAM
|
|
|
|
#include <dm.h>
|
|
#include <init.h>
|
|
#include <log.h>
|
|
#include <pci.h>
|
|
#include <syscon.h>
|
|
#include <asm/cpu.h>
|
|
#include <asm/global_data.h>
|
|
#include <asm/io.h>
|
|
#include <asm/lpc_common.h>
|
|
#include <asm/mrccache.h>
|
|
#include <asm/mrc_common.h>
|
|
#include <asm/mtrr.h>
|
|
#include <asm/pci.h>
|
|
#include <asm/arch/iomap.h>
|
|
#include <asm/arch/me.h>
|
|
#include <asm/arch/pch.h>
|
|
#include <asm/arch/pei_data.h>
|
|
#include <asm/arch/pm.h>
|
|
|
|
phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
|
|
{
|
|
return mrc_common_board_get_usable_ram_top(total_size);
|
|
}
|
|
|
|
int dram_init_banksize(void)
|
|
{
|
|
mrc_common_dram_init_banksize();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long get_top_of_ram(struct udevice *dev)
|
|
{
|
|
/*
|
|
* Base of DPR is top of usable DRAM below 4GiB. The register has
|
|
* 1 MiB alignment and reports the TOP of the range, the base
|
|
* must be calculated from the size in MiB in bits 11:4.
|
|
*/
|
|
u32 dpr, tom;
|
|
|
|
dm_pci_read_config32(dev, DPR, &dpr);
|
|
tom = dpr & ~((1 << 20) - 1);
|
|
|
|
debug("dpt %08x tom %08x\n", dpr, tom);
|
|
/* Subtract DMA Protected Range size if enabled */
|
|
if (dpr & DPR_EPM)
|
|
tom -= (dpr & DPR_SIZE_MASK) << 16;
|
|
|
|
return (unsigned long)tom;
|
|
}
|
|
|
|
/**
|
|
* sdram_find() - Find available memory
|
|
*
|
|
* This is a bit complicated since on x86 there are system memory holes all
|
|
* over the place. We create a list of available memory blocks
|
|
*
|
|
* @dev: Northbridge device
|
|
*/
|
|
static int sdram_find(struct udevice *dev)
|
|
{
|
|
struct memory_info *info = &gd->arch.meminfo;
|
|
ulong top_of_ram;
|
|
|
|
top_of_ram = get_top_of_ram(dev);
|
|
mrc_add_memory_area(info, 0, top_of_ram);
|
|
|
|
/* Add MTRRs for memory */
|
|
mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int prepare_mrc_cache(struct pei_data *pei_data)
|
|
{
|
|
struct mrc_data_container *mrc_cache;
|
|
struct mrc_region entry;
|
|
int ret;
|
|
|
|
ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
|
|
if (ret)
|
|
return ret;
|
|
mrc_cache = mrccache_find_current(&entry);
|
|
if (!mrc_cache)
|
|
return -ENOENT;
|
|
|
|
pei_data->saved_data = mrc_cache->data;
|
|
pei_data->saved_data_size = mrc_cache->data_size;
|
|
debug("%s: at %p, size %x checksum %04x\n", __func__,
|
|
pei_data->saved_data, pei_data->saved_data_size,
|
|
mrc_cache->checksum);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dram_init(void)
|
|
{
|
|
struct pei_data _pei_data __aligned(8);
|
|
struct pei_data *pei_data = &_pei_data;
|
|
struct udevice *dev, *me_dev, *pch_dev;
|
|
struct chipset_power_state ps;
|
|
const void *spd_data;
|
|
int ret, size;
|
|
|
|
memset(pei_data, '\0', sizeof(struct pei_data));
|
|
|
|
/* Print ME state before MRC */
|
|
ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
|
|
if (ret) {
|
|
debug("Cannot get ME (err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
intel_me_status(me_dev);
|
|
|
|
/* Save ME HSIO version */
|
|
ret = uclass_first_device_err(UCLASS_PCH, &pch_dev);
|
|
if (ret) {
|
|
debug("Cannot get PCH (err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
power_state_get(pch_dev, &ps);
|
|
|
|
intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum);
|
|
|
|
broadwell_fill_pei_data(pei_data);
|
|
mainboard_fill_pei_data(pei_data);
|
|
|
|
ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
|
|
if (ret) {
|
|
debug("Cannot get Northbridge (err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
size = 256;
|
|
ret = mrc_locate_spd(dev, size, &spd_data);
|
|
if (ret) {
|
|
debug("Cannot locate SPD (err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
memcpy(pei_data->spd_data[0][0], spd_data, size);
|
|
memcpy(pei_data->spd_data[1][0], spd_data, size);
|
|
|
|
ret = prepare_mrc_cache(pei_data);
|
|
if (ret)
|
|
debug("prepare_mrc_cache failed: %d\n", ret);
|
|
|
|
debug("PEI version %#x\n", pei_data->pei_version);
|
|
ret = mrc_common_init(dev, pei_data, true);
|
|
if (ret) {
|
|
debug("mrc_common_init() failed(err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
debug("Memory init done\n");
|
|
|
|
ret = sdram_find(dev);
|
|
if (ret) {
|
|
debug("sdram_find() failed (err=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
gd->ram_size = gd->arch.meminfo.total_32bit_memory;
|
|
debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
|
|
|
|
debug("MRC output data length %#x at %p\n", pei_data->data_to_save_size,
|
|
pei_data->data_to_save);
|
|
/* S3 resume: don't save scrambler seed or MRC data */
|
|
if (pei_data->boot_mode != SLEEP_STATE_S3) {
|
|
struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
|
|
|
|
/*
|
|
* This will be copied to SDRAM in reserve_arch(), then written
|
|
* to SPI flash in mrccache_save()
|
|
*/
|
|
mrc->buf = (char *)pei_data->data_to_save;
|
|
mrc->len = pei_data->data_to_save_size;
|
|
}
|
|
gd->arch.pei_meminfo = pei_data->meminfo;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Use this hook to save our SDRAM parameters */
|
|
int misc_init_r(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = mrccache_save();
|
|
if (ret)
|
|
printf("Unable to save MRC data: %d\n", ret);
|
|
else
|
|
debug("Saved MRC cache data\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct udevice_id broadwell_syscon_ids[] = {
|
|
{ .compatible = "intel,me", .data = X86_SYSCON_ME },
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(syscon_intel_me_broadwell) = {
|
|
.name = "intel_me_syscon",
|
|
.id = UCLASS_SYSCON,
|
|
.of_match = broadwell_syscon_ids,
|
|
};
|