Prepare v2023.10
[platform/kernel/u-boot.git] / arch / arm / mach-socfpga / wrap_handoff_soc64.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
4  *
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
13 static 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
41 static 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
59 int socfpga_get_handoff_size(void *handoff_address)
60 {
61         u32 size;
62         int ret;
63         enum endianness endian_t;
64
65         ret = getting_endianness(handoff_address, &endian_t);
66         if (ret)
67                 return ret;
68
69         size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
70         if (endian_t == BIG_ENDIAN)
71                 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
81 int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
82 {
83         u32 temp;
84         u32 *table_x32 = table;
85         u32 i = 0;
86         int ret;
87         enum endianness endian_t;
88
89         ret = getting_endianness(handoff_address, &endian_t);
90         if (ret)
91                 return ret;
92
93         temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
94                     (i * sizeof(u32)));
95
96         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         }
106
107         debug(" No.%d Addr 0x%08x: ", i, *table_x32);
108
109         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);
126         }
127         debug("\n}\n");
128
129         return 0;
130 }