blob: df0701ec85ed7b6556a9d026480b881ea691cca3 [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
Maxim Uvarov40575d72023-12-26 21:46:16 +060013#ifndef __ASSEMBLY__
14#include <asm/types.h>
15enum 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:
31 case SOC64_HANDOFF_MAGIC_MISC:
32 return BIG_ENDIAN;
33#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
34 case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
35 debug("%s: umctl2 handoff data\n", __func__);
36 return LITTLE_ENDIAN;
37 case SOC64_HANDOFF_DDR_PHY_MAGIC:
38 debug("%s: PHY handoff data\n", __func__);
39 return LITTLE_ENDIAN;
40 case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
41 debug("%s: PHY engine handoff data\n", __func__);
42 return LITTLE_ENDIAN;
43#endif
44 default:
45 debug("%s: Unknown endianness!!\n", __func__);
46 return UNKNOWN_ENDIANNESS;
47 }
48}
49
50static int getting_endianness(void *handoff_address, enum endianness *endian_t)
51{
52 /* Checking handoff data is little endian ? */
53 *endian_t = check_endianness(readl(handoff_address));
54
55 if (*endian_t == UNKNOWN_ENDIANNESS) {
56 /* Trying to check handoff data is big endian? */
57 *endian_t = check_endianness(swab32(readl(handoff_address)));
58 if (*endian_t == UNKNOWN_ENDIANNESS) {
59 debug("%s: Cannot find HANDOFF MAGIC ", __func__);
60 debug("at addr 0x%p\n", (u32 *)handoff_address);
61 return -EPERM;
62 }
63 }
64
65 return 0;
66}
67
68int socfpga_get_handoff_size(void *handoff_address)
Siew Chin Limff1eec32021-03-24 13:11:38 +080069{
70 u32 size;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080071 int ret;
72 enum endianness endian_t;
73
74 ret = getting_endianness(handoff_address, &endian_t);
75 if (ret)
76 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080077
78 size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
Tien Fong Cheedf89b502021-08-10 11:26:29 +080079 if (endian_t == BIG_ENDIAN)
Siew Chin Limff1eec32021-03-24 13:11:38 +080080 size = swab32(size);
81
82 size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
83
84 debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
85 (u32 *)handoff_address, size);
86
87 return size;
88}
89
Tien Fong Cheedf89b502021-08-10 11:26:29 +080090int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
Siew Chin Limff1eec32021-03-24 13:11:38 +080091{
Tien Fong Cheedf89b502021-08-10 11:26:29 +080092 u32 temp;
Siew Chin Limff1eec32021-03-24 13:11:38 +080093 u32 *table_x32 = table;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080094 u32 i = 0;
95 int ret;
96 enum endianness endian_t;
Siew Chin Limff1eec32021-03-24 13:11:38 +080097
Tien Fong Cheedf89b502021-08-10 11:26:29 +080098 ret = getting_endianness(handoff_address, &endian_t);
99 if (ret)
100 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +0800101
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800102 temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
103 (i * sizeof(u32)));
Siew Chin Limff1eec32021-03-24 13:11:38 +0800104
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800105 if (endian_t == BIG_ENDIAN) {
106 debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
107 debug("Handoff table address = 0x%p ", table_x32);
108 debug("table length = 0x%x\n", table_len);
109 debug("%s: handoff data =\n{\n", __func__);
110 *table_x32 = swab32(temp);
111 } else if (endian_t == LITTLE_ENDIAN) {
112 debug(" {\n");
113 *table_x32 = temp;
114 }
Siew Chin Limff1eec32021-03-24 13:11:38 +0800115
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800116 debug(" No.%d Addr 0x%08x: ", i, *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800117
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800118 for (i = 1; i < table_len; i++) {
119 table_x32++;
120
121 temp = readl(handoff_address +
122 SOC64_HANDOFF_OFFSET_DATA +
123 (i * sizeof(u32)));
124
125 if (endian_t == BIG_ENDIAN)
126 *table_x32 = swab32(temp);
127 else if (endian_t == LITTLE_ENDIAN)
128 *table_x32 = temp;
129
130 if (!(i % 2))
131 debug(" No.%d Addr 0x%08x: ", i,
132 *table_x32);
133 else
134 debug(" 0x%08x\n", *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800135 }
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800136 debug("\n}\n");
Siew Chin Limff1eec32021-03-24 13:11:38 +0800137
138 return 0;
139}