mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
2fb2e04791
N5X support both HPS handoff data and DDR handoff data. Existing HPS handoff functions are restructured to support both existing devices and N5X device. Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
130 lines
3.1 KiB
C
130 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
|
|
*
|
|
*/
|
|
|
|
#include <asm/arch/handoff_soc64.h>
|
|
#include <asm/io.h>
|
|
#include <common.h>
|
|
#include <errno.h>
|
|
#include "log.h"
|
|
|
|
static enum endianness check_endianness(u32 handoff)
|
|
{
|
|
switch (handoff) {
|
|
case SOC64_HANDOFF_MAGIC_BOOT:
|
|
case SOC64_HANDOFF_MAGIC_MUX:
|
|
case SOC64_HANDOFF_MAGIC_IOCTL:
|
|
case SOC64_HANDOFF_MAGIC_FPGA:
|
|
case SOC64_HANDOFF_MAGIC_DELAY:
|
|
case SOC64_HANDOFF_MAGIC_CLOCK:
|
|
case SOC64_HANDOFF_MAGIC_MISC:
|
|
return BIG_ENDIAN;
|
|
#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
|
|
case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
|
|
debug("%s: umctl2 handoff data\n", __func__);
|
|
return LITTLE_ENDIAN;
|
|
case SOC64_HANDOFF_DDR_PHY_MAGIC:
|
|
debug("%s: PHY handoff data\n", __func__);
|
|
return LITTLE_ENDIAN;
|
|
case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
|
|
debug("%s: PHY engine handoff data\n", __func__);
|
|
return LITTLE_ENDIAN;
|
|
#endif
|
|
default:
|
|
debug("%s: Unknown endianness!!\n", __func__);
|
|
return UNKNOWN_ENDIANNESS;
|
|
}
|
|
}
|
|
|
|
static int getting_endianness(void *handoff_address, enum endianness *endian_t)
|
|
{
|
|
/* Checking handoff data is little endian ? */
|
|
*endian_t = check_endianness(readl(handoff_address));
|
|
|
|
if (*endian_t == UNKNOWN_ENDIANNESS) {
|
|
/* Trying to check handoff data is big endian? */
|
|
*endian_t = check_endianness(swab32(readl(handoff_address)));
|
|
if (*endian_t == UNKNOWN_ENDIANNESS) {
|
|
debug("%s: Cannot find HANDOFF MAGIC ", __func__);
|
|
debug("at addr 0x%p\n", (u32 *)handoff_address);
|
|
return -EPERM;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int socfpga_get_handoff_size(void *handoff_address)
|
|
{
|
|
u32 size;
|
|
int ret;
|
|
enum endianness endian_t;
|
|
|
|
ret = getting_endianness(handoff_address, &endian_t);
|
|
if (ret)
|
|
return ret;
|
|
|
|
size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
|
|
if (endian_t == BIG_ENDIAN)
|
|
size = swab32(size);
|
|
|
|
size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
|
|
|
|
debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
|
|
(u32 *)handoff_address, size);
|
|
|
|
return size;
|
|
}
|
|
|
|
int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
|
|
{
|
|
u32 temp;
|
|
u32 *table_x32 = table;
|
|
u32 i = 0;
|
|
int ret;
|
|
enum endianness endian_t;
|
|
|
|
ret = getting_endianness(handoff_address, &endian_t);
|
|
if (ret)
|
|
return ret;
|
|
|
|
temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
|
|
(i * sizeof(u32)));
|
|
|
|
if (endian_t == BIG_ENDIAN) {
|
|
debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
|
|
debug("Handoff table address = 0x%p ", table_x32);
|
|
debug("table length = 0x%x\n", table_len);
|
|
debug("%s: handoff data =\n{\n", __func__);
|
|
*table_x32 = swab32(temp);
|
|
} else if (endian_t == LITTLE_ENDIAN) {
|
|
debug(" {\n");
|
|
*table_x32 = temp;
|
|
}
|
|
|
|
debug(" No.%d Addr 0x%08x: ", i, *table_x32);
|
|
|
|
for (i = 1; i < table_len; i++) {
|
|
table_x32++;
|
|
|
|
temp = readl(handoff_address +
|
|
SOC64_HANDOFF_OFFSET_DATA +
|
|
(i * sizeof(u32)));
|
|
|
|
if (endian_t == BIG_ENDIAN)
|
|
*table_x32 = swab32(temp);
|
|
else if (endian_t == LITTLE_ENDIAN)
|
|
*table_x32 = temp;
|
|
|
|
if (!(i % 2))
|
|
debug(" No.%d Addr 0x%08x: ", i,
|
|
*table_x32);
|
|
else
|
|
debug(" 0x%08x\n", *table_x32);
|
|
}
|
|
debug("\n}\n");
|
|
|
|
return 0;
|
|
}
|