blob: 6aa9bb26b4ec1f3c41b74b02a5a042a822110f31 [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__
Maxim Uvarov40575d72023-12-26 21:46:16 +060014enum endianness {
15 LITTLE_ENDIAN = 0,
16 BIG_ENDIAN,
17 UNKNOWN_ENDIANNESS
18};
19#endif
20
Tien Fong Cheedf89b502021-08-10 11:26:29 +080021static enum endianness check_endianness(u32 handoff)
22{
23 switch (handoff) {
24 case SOC64_HANDOFF_MAGIC_BOOT:
25 case SOC64_HANDOFF_MAGIC_MUX:
26 case SOC64_HANDOFF_MAGIC_IOCTL:
27 case SOC64_HANDOFF_MAGIC_FPGA:
28 case SOC64_HANDOFF_MAGIC_DELAY:
29 case SOC64_HANDOFF_MAGIC_CLOCK:
30 case SOC64_HANDOFF_MAGIC_MISC:
31 return BIG_ENDIAN;
32#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
33 case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
34 debug("%s: umctl2 handoff data\n", __func__);
35 return LITTLE_ENDIAN;
36 case SOC64_HANDOFF_DDR_PHY_MAGIC:
37 debug("%s: PHY handoff data\n", __func__);
38 return LITTLE_ENDIAN;
39 case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
40 debug("%s: PHY engine handoff data\n", __func__);
41 return LITTLE_ENDIAN;
42#endif
43 default:
44 debug("%s: Unknown endianness!!\n", __func__);
45 return UNKNOWN_ENDIANNESS;
46 }
47}
48
49static int getting_endianness(void *handoff_address, enum endianness *endian_t)
50{
51 /* Checking handoff data is little endian ? */
52 *endian_t = check_endianness(readl(handoff_address));
53
54 if (*endian_t == UNKNOWN_ENDIANNESS) {
55 /* Trying to check handoff data is big endian? */
56 *endian_t = check_endianness(swab32(readl(handoff_address)));
57 if (*endian_t == UNKNOWN_ENDIANNESS) {
58 debug("%s: Cannot find HANDOFF MAGIC ", __func__);
59 debug("at addr 0x%p\n", (u32 *)handoff_address);
60 return -EPERM;
61 }
62 }
63
64 return 0;
65}
66
67int socfpga_get_handoff_size(void *handoff_address)
Siew Chin Limff1eec32021-03-24 13:11:38 +080068{
69 u32 size;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080070 int ret;
71 enum endianness endian_t;
72
73 ret = getting_endianness(handoff_address, &endian_t);
74 if (ret)
75 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +080076
77 size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
Tien Fong Cheedf89b502021-08-10 11:26:29 +080078 if (endian_t == BIG_ENDIAN)
Siew Chin Limff1eec32021-03-24 13:11:38 +080079 size = swab32(size);
80
81 size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
82
83 debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
84 (u32 *)handoff_address, size);
85
86 return size;
87}
88
Tien Fong Cheedf89b502021-08-10 11:26:29 +080089int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
Siew Chin Limff1eec32021-03-24 13:11:38 +080090{
Tien Fong Cheedf89b502021-08-10 11:26:29 +080091 u32 temp;
Siew Chin Limff1eec32021-03-24 13:11:38 +080092 u32 *table_x32 = table;
Tien Fong Cheedf89b502021-08-10 11:26:29 +080093 u32 i = 0;
94 int ret;
95 enum endianness endian_t;
Siew Chin Limff1eec32021-03-24 13:11:38 +080096
Tien Fong Cheedf89b502021-08-10 11:26:29 +080097 ret = getting_endianness(handoff_address, &endian_t);
98 if (ret)
99 return ret;
Siew Chin Limff1eec32021-03-24 13:11:38 +0800100
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800101 temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
102 (i * sizeof(u32)));
Siew Chin Limff1eec32021-03-24 13:11:38 +0800103
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800104 if (endian_t == BIG_ENDIAN) {
105 debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
106 debug("Handoff table address = 0x%p ", table_x32);
107 debug("table length = 0x%x\n", table_len);
108 debug("%s: handoff data =\n{\n", __func__);
109 *table_x32 = swab32(temp);
110 } else if (endian_t == LITTLE_ENDIAN) {
111 debug(" {\n");
112 *table_x32 = temp;
113 }
Siew Chin Limff1eec32021-03-24 13:11:38 +0800114
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800115 debug(" No.%d Addr 0x%08x: ", i, *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800116
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800117 for (i = 1; i < table_len; i++) {
118 table_x32++;
119
120 temp = readl(handoff_address +
121 SOC64_HANDOFF_OFFSET_DATA +
122 (i * sizeof(u32)));
123
124 if (endian_t == BIG_ENDIAN)
125 *table_x32 = swab32(temp);
126 else if (endian_t == LITTLE_ENDIAN)
127 *table_x32 = temp;
128
129 if (!(i % 2))
130 debug(" No.%d Addr 0x%08x: ", i,
131 *table_x32);
132 else
133 debug(" 0x%08x\n", *table_x32);
Siew Chin Limff1eec32021-03-24 13:11:38 +0800134 }
Tien Fong Cheedf89b502021-08-10 11:26:29 +0800135 debug("\n}\n");
Siew Chin Limff1eec32021-03-24 13:11:38 +0800136
137 return 0;
138}