blob: 92051d19b737ad761c2da7b28f5835af05ae9f34 [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>
Siew Chin Limff1eec32021-03-24 13:11:38 +08009#include <errno.h>
10#include "log.h"
11
Maxim Uvarov40575d72023-12-26 21:46:16 +060012#ifndef __ASSEMBLY__
Maxim Uvarov40575d72023-12-26 21:46:16 +060013enum endianness {
14 LITTLE_ENDIAN = 0,
15 BIG_ENDIAN,
16 UNKNOWN_ENDIANNESS
17};
18#endif
19
Tien Fong Cheedf89b502021-08-10 11:26:29 +080020static enum endianness check_endianness(u32 handoff)
21{
22 switch (handoff) {
23 case SOC64_HANDOFF_MAGIC_BOOT:
24 case SOC64_HANDOFF_MAGIC_MUX:
25 case SOC64_HANDOFF_MAGIC_IOCTL:
26 case SOC64_HANDOFF_MAGIC_FPGA:
27 case SOC64_HANDOFF_MAGIC_DELAY:
28 case SOC64_HANDOFF_MAGIC_CLOCK:
29 case SOC64_HANDOFF_MAGIC_MISC:
30 return BIG_ENDIAN;
31#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
32 case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
33 debug("%s: umctl2 handoff data\n", __func__);
34 return LITTLE_ENDIAN;
35 case SOC64_HANDOFF_DDR_PHY_MAGIC:
36 debug("%s: PHY handoff data\n", __func__);
37 return LITTLE_ENDIAN;
38 case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
39 debug("%s: PHY engine handoff data\n", __func__);
40 return LITTLE_ENDIAN;
41#endif
42 default:
43 debug("%s: Unknown endianness!!\n", __func__);
44 return UNKNOWN_ENDIANNESS;
45 }
46}
47
48static int getting_endianness(void *handoff_address, enum endianness *endian_t)
49{
50 /* Checking handoff data is little endian ? */
51 *endian_t = check_endianness(readl(handoff_address));
52
53 if (*endian_t == UNKNOWN_ENDIANNESS) {
54 /* Trying to check handoff data is big endian? */
55 *endian_t = check_endianness(swab32(readl(handoff_address)));
56 if (*endian_t == UNKNOWN_ENDIANNESS) {
57 debug("%s: Cannot find HANDOFF MAGIC ", __func__);
58 debug("at addr 0x%p\n", (u32 *)handoff_address);
59 return -EPERM;
60 }
61 }
62
63 return 0;
64}
65
66int socfpga_get_handoff_size(void *handoff_address)
Siew Chin Limff1eec32021-03-24 13:11:38 +080067{
68 u32 size;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080069 int ret;
70 enum endianness endian_t;
71
72 ret = getting_endianness(handoff_address, &endian_t);
73 if (ret)
74 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080075
76 size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
Tien Fong Cheedf89b502021-08-10 11:26:29 +080077 if (endian_t == BIG_ENDIAN)
Siew Chin Limff1eec32021-03-24 13:11:38 +080078 size = swab32(size);
79
80 size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
81
82 debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
83 (u32 *)handoff_address, size);
84
85 return size;
86}
87
Tien Fong Cheedf89b502021-08-10 11:26:29 +080088int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
Siew Chin Limff1eec32021-03-24 13:11:38 +080089{
Tien Fong Cheedf89b502021-08-10 11:26:29 +080090 u32 temp;
Siew Chin Limff1eec32021-03-24 13:11:38 +080091 u32 *table_x32 = table;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080092 u32 i = 0;
93 int ret;
94 enum endianness endian_t;
Siew Chin Limff1eec32021-03-24 13:11:38 +080095
Tien Fong Cheedf89b502021-08-10 11:26:29 +080096 ret = getting_endianness(handoff_address, &endian_t);
97 if (ret)
98 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080099
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800100 temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
101 (i * sizeof(u32)));
Siew Chin Limff1eec32021-03-24 13:11:38 +0800102
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800103 if (endian_t == BIG_ENDIAN) {
104 debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
105 debug("Handoff table address = 0x%p ", table_x32);
106 debug("table length = 0x%x\n", table_len);
107 debug("%s: handoff data =\n{\n", __func__);
108 *table_x32 = swab32(temp);
109 } else if (endian_t == LITTLE_ENDIAN) {
110 debug(" {\n");
111 *table_x32 = temp;
112 }
Siew Chin Limff1eec32021-03-24 13:11:38 +0800113
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800114 debug(" No.%d Addr 0x%08x: ", i, *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800115
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800116 for (i = 1; i < table_len; i++) {
117 table_x32++;
118
119 temp = readl(handoff_address +
120 SOC64_HANDOFF_OFFSET_DATA +
121 (i * sizeof(u32)));
122
123 if (endian_t == BIG_ENDIAN)
124 *table_x32 = swab32(temp);
125 else if (endian_t == LITTLE_ENDIAN)
126 *table_x32 = temp;
127
128 if (!(i % 2))
129 debug(" No.%d Addr 0x%08x: ", i,
130 *table_x32);
131 else
132 debug(" 0x%08x\n", *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800133 }
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800134 debug("\n}\n");
Siew Chin Limff1eec32021-03-24 13:11:38 +0800135
136 return 0;
137}