// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
*
*/
#include <errno.h>
#include "log.h"
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
+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 == BIG_ENDIAN)
+ if (endian_t == BIG_ENDIAN)
size = swab32(size);
size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
return size;
}
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
- enum endianness big_endian)
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
{
- u32 temp, i;
+ u32 temp;
u32 *table_x32 = table;
+ u32 i = 0;
+ int ret;
+ enum endianness endian_t;
- debug("%s: handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
-
- if (big_endian) {
- if (swab32(readl(SOC64_HANDOFF_BASE)) == SOC64_HANDOFF_MAGIC_BOOT) {
- debug("Handoff table address = 0x%p ", table_x32);
- debug("table length = 0x%x\n", table_len);
- debug("%s: handoff data =\n{\n", __func__);
-
- for (i = 0; i < table_len; i++) {
- temp = readl(handoff_address +
- SOC64_HANDOFF_OFFSET_DATA +
- (i * sizeof(u32)));
- *table_x32 = swab32(temp);
-
- if (!(i % 2))
- debug(" No.%d Addr 0x%08x: ", i,
- *table_x32);
- else
- debug(" 0x%08x\n", *table_x32);
-
- table_x32++;
- }
- debug("\n}\n");
- } else {
- debug("%s: Cannot find SOC64_HANDOFF_MAGIC_BOOT ", __func__);
- debug("at addr 0x%p\n", (u32 *)handoff_address);
- return -EPERM;
- }
+ 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;
}