blob: e7cb5ea89cc6cae9463da9ec6b49c7603cd7f336 [file] [log] [blame]
Siew Chin Limff1eec32021-03-24 13:11:38 +08001// SPDX-License-Identifier: GPL-2.0
2/*
Tien Fong Cheedf89b502021-08-10 11:26:29 +08003 * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
Siew Chin Limff1eec32021-03-24 13:11:38 +08004 *
5 */
6
7#include <asm/arch/handoff_soc64.h>
8#include <asm/io.h>
9#include <common.h>
10#include <errno.h>
11#include "log.h"
12
Tien Fong Cheedf89b502021-08-10 11:26:29 +080013static enum endianness check_endianness(u32 handoff)
14{
15 switch (handoff) {
16 case SOC64_HANDOFF_MAGIC_BOOT:
17 case SOC64_HANDOFF_MAGIC_MUX:
18 case SOC64_HANDOFF_MAGIC_IOCTL:
19 case SOC64_HANDOFF_MAGIC_FPGA:
20 case SOC64_HANDOFF_MAGIC_DELAY:
21 case SOC64_HANDOFF_MAGIC_CLOCK:
22 case SOC64_HANDOFF_MAGIC_MISC:
23 return BIG_ENDIAN;
24#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
25 case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
26 debug("%s: umctl2 handoff data\n", __func__);
27 return LITTLE_ENDIAN;
28 case SOC64_HANDOFF_DDR_PHY_MAGIC:
29 debug("%s: PHY handoff data\n", __func__);
30 return LITTLE_ENDIAN;
31 case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
32 debug("%s: PHY engine handoff data\n", __func__);
33 return LITTLE_ENDIAN;
34#endif
35 default:
36 debug("%s: Unknown endianness!!\n", __func__);
37 return UNKNOWN_ENDIANNESS;
38 }
39}
40
41static int getting_endianness(void *handoff_address, enum endianness *endian_t)
42{
43 /* Checking handoff data is little endian ? */
44 *endian_t = check_endianness(readl(handoff_address));
45
46 if (*endian_t == UNKNOWN_ENDIANNESS) {
47 /* Trying to check handoff data is big endian? */
48 *endian_t = check_endianness(swab32(readl(handoff_address)));
49 if (*endian_t == UNKNOWN_ENDIANNESS) {
50 debug("%s: Cannot find HANDOFF MAGIC ", __func__);
51 debug("at addr 0x%p\n", (u32 *)handoff_address);
52 return -EPERM;
53 }
54 }
55
56 return 0;
57}
58
59int socfpga_get_handoff_size(void *handoff_address)
Siew Chin Limff1eec32021-03-24 13:11:38 +080060{
61 u32 size;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080062 int ret;
63 enum endianness endian_t;
64
65 ret = getting_endianness(handoff_address, &endian_t);
66 if (ret)
67 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080068
69 size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
Tien Fong Cheedf89b502021-08-10 11:26:29 +080070 if (endian_t == BIG_ENDIAN)
Siew Chin Limff1eec32021-03-24 13:11:38 +080071 size = swab32(size);
72
73 size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
74
75 debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
76 (u32 *)handoff_address, size);
77
78 return size;
79}
80
Tien Fong Cheedf89b502021-08-10 11:26:29 +080081int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
Siew Chin Limff1eec32021-03-24 13:11:38 +080082{
Tien Fong Cheedf89b502021-08-10 11:26:29 +080083 u32 temp;
Siew Chin Limff1eec32021-03-24 13:11:38 +080084 u32 *table_x32 = table;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080085 u32 i = 0;
86 int ret;
87 enum endianness endian_t;
Siew Chin Limff1eec32021-03-24 13:11:38 +080088
Tien Fong Cheedf89b502021-08-10 11:26:29 +080089 ret = getting_endianness(handoff_address, &endian_t);
90 if (ret)
91 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080092
Tien Fong Cheedf89b502021-08-10 11:26:29 +080093 temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
94 (i * sizeof(u32)));
Siew Chin Limff1eec32021-03-24 13:11:38 +080095
Tien Fong Cheedf89b502021-08-10 11:26:29 +080096 if (endian_t == BIG_ENDIAN) {
97 debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
98 debug("Handoff table address = 0x%p ", table_x32);
99 debug("table length = 0x%x\n", table_len);
100 debug("%s: handoff data =\n{\n", __func__);
101 *table_x32 = swab32(temp);
102 } else if (endian_t == LITTLE_ENDIAN) {
103 debug(" {\n");
104 *table_x32 = temp;
105 }
Siew Chin Limff1eec32021-03-24 13:11:38 +0800106
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800107 debug(" No.%d Addr 0x%08x: ", i, *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800108
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800109 for (i = 1; i < table_len; i++) {
110 table_x32++;
111
112 temp = readl(handoff_address +
113 SOC64_HANDOFF_OFFSET_DATA +
114 (i * sizeof(u32)));
115
116 if (endian_t == BIG_ENDIAN)
117 *table_x32 = swab32(temp);
118 else if (endian_t == LITTLE_ENDIAN)
119 *table_x32 = temp;
120
121 if (!(i % 2))
122 debug(" No.%d Addr 0x%08x: ", i,
123 *table_x32);
124 else
125 debug(" 0x%08x\n", *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800126 }
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800127 debug("\n}\n");
Siew Chin Limff1eec32021-03-24 13:11:38 +0800128
129 return 0;
130}