blob: 7105cdc490525d75dad592dfd7117f790a4791fe [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>
Tien Fong Cheee2e79dd2024-07-24 17:35:09 +08004 * Copyright (C) 2025 Altera Corporation <www.altera.com>
Siew Chin Limff1eec32021-03-24 13:11:38 +08005 *
6 */
7
Tien Fong Cheee2e79dd2024-07-24 17:35:09 +08008#include <errno.h>
Siew Chin Limff1eec32021-03-24 13:11:38 +08009#include <asm/arch/handoff_soc64.h>
10#include <asm/io.h>
Siew Chin Limff1eec32021-03-24 13:11:38 +080011#include "log.h"
12
Maxim Uvarov40575d72023-12-26 21:46:16 +060013#ifndef __ASSEMBLY__
Tien Fong Cheee2e79dd2024-07-24 17:35:09 +080014#include <asm/types.h>
Maxim Uvarov40575d72023-12-26 21:46:16 +060015enum endianness {
16 LITTLE_ENDIAN = 0,
17 BIG_ENDIAN,
18 UNKNOWN_ENDIANNESS
19};
20#endif
21
Tien Fong Cheedf89b502021-08-10 11:26:29 +080022static enum endianness check_endianness(u32 handoff)
23{
24 switch (handoff) {
25 case SOC64_HANDOFF_MAGIC_BOOT:
26 case SOC64_HANDOFF_MAGIC_MUX:
27 case SOC64_HANDOFF_MAGIC_IOCTL:
28 case SOC64_HANDOFF_MAGIC_FPGA:
29 case SOC64_HANDOFF_MAGIC_DELAY:
30 case SOC64_HANDOFF_MAGIC_CLOCK:
Tien Fong Cheee2e79dd2024-07-24 17:35:09 +080031 case SOC64_HANDOFF_MAGIC_SDRAM:
32#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
33 case SOC64_HANDOFF_MAGIC_PERI:
34#else
Tien Fong Cheedf89b502021-08-10 11:26:29 +080035 case SOC64_HANDOFF_MAGIC_MISC:
Tien Fong Cheee2e79dd2024-07-24 17:35:09 +080036#endif
Tien Fong Cheedf89b502021-08-10 11:26:29 +080037 return BIG_ENDIAN;
38#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
39 case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
40 debug("%s: umctl2 handoff data\n", __func__);
41 return LITTLE_ENDIAN;
42 case SOC64_HANDOFF_DDR_PHY_MAGIC:
43 debug("%s: PHY handoff data\n", __func__);
44 return LITTLE_ENDIAN;
45 case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
46 debug("%s: PHY engine handoff data\n", __func__);
47 return LITTLE_ENDIAN;
48#endif
49 default:
50 debug("%s: Unknown endianness!!\n", __func__);
51 return UNKNOWN_ENDIANNESS;
52 }
53}
54
55static int getting_endianness(void *handoff_address, enum endianness *endian_t)
56{
57 /* Checking handoff data is little endian ? */
58 *endian_t = check_endianness(readl(handoff_address));
59
60 if (*endian_t == UNKNOWN_ENDIANNESS) {
61 /* Trying to check handoff data is big endian? */
62 *endian_t = check_endianness(swab32(readl(handoff_address)));
63 if (*endian_t == UNKNOWN_ENDIANNESS) {
64 debug("%s: Cannot find HANDOFF MAGIC ", __func__);
65 debug("at addr 0x%p\n", (u32 *)handoff_address);
66 return -EPERM;
67 }
68 }
69
70 return 0;
71}
72
73int socfpga_get_handoff_size(void *handoff_address)
Siew Chin Limff1eec32021-03-24 13:11:38 +080074{
75 u32 size;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080076 int ret;
77 enum endianness endian_t;
78
79 ret = getting_endianness(handoff_address, &endian_t);
80 if (ret)
81 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080082
83 size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
Tien Fong Cheedf89b502021-08-10 11:26:29 +080084 if (endian_t == BIG_ENDIAN)
Siew Chin Limff1eec32021-03-24 13:11:38 +080085 size = swab32(size);
86
87 size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
88
89 debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
90 (u32 *)handoff_address, size);
91
92 return size;
93}
94
Tien Fong Cheedf89b502021-08-10 11:26:29 +080095int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
Siew Chin Limff1eec32021-03-24 13:11:38 +080096{
Tien Fong Cheedf89b502021-08-10 11:26:29 +080097 u32 temp;
Siew Chin Limff1eec32021-03-24 13:11:38 +080098 u32 *table_x32 = table;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080099 u32 i = 0;
100 int ret;
101 enum endianness endian_t;
Siew Chin Limff1eec32021-03-24 13:11:38 +0800102
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800103 ret = getting_endianness(handoff_address, &endian_t);
104 if (ret)
105 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +0800106
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800107 temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
108 (i * sizeof(u32)));
Siew Chin Limff1eec32021-03-24 13:11:38 +0800109
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800110 if (endian_t == BIG_ENDIAN) {
111 debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
112 debug("Handoff table address = 0x%p ", table_x32);
113 debug("table length = 0x%x\n", table_len);
114 debug("%s: handoff data =\n{\n", __func__);
115 *table_x32 = swab32(temp);
116 } else if (endian_t == LITTLE_ENDIAN) {
117 debug(" {\n");
118 *table_x32 = temp;
119 }
Siew Chin Limff1eec32021-03-24 13:11:38 +0800120
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800121 debug(" No.%d Addr 0x%08x: ", i, *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800122
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800123 for (i = 1; i < table_len; i++) {
124 table_x32++;
125
126 temp = readl(handoff_address +
127 SOC64_HANDOFF_OFFSET_DATA +
128 (i * sizeof(u32)));
129
130 if (endian_t == BIG_ENDIAN)
131 *table_x32 = swab32(temp);
132 else if (endian_t == LITTLE_ENDIAN)
133 *table_x32 = temp;
134
135 if (!(i % 2))
136 debug(" No.%d Addr 0x%08x: ", i,
137 *table_x32);
138 else
139 debug(" 0x%08x\n", *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800140 }
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800141 debug("\n}\n");
Siew Chin Limff1eec32021-03-24 13:11:38 +0800142
143 return 0;
144}