1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2018 Marvell International Ltd.
4 *
5 * https://spdx.org/licenses
6 */
7
8 #include <errno.h>
9 #include <fdtdec.h>
10 #include <fdt_support.h>
11 #include <log.h>
12
13 #include <linux/compiler.h>
14 #include <linux/libfdt.h>
15
16 #include <asm/arch/board.h>
17 #include <asm/arch/smc.h>
18 #include <asm/global_data.h>
19 #include <asm/io.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
fdt_get_bdk_node(void)23 static int fdt_get_bdk_node(void)
24 {
25 int node, ret;
26 const void *fdt = gd->fdt_blob;
27
28 if (!fdt) {
29 printf("ERROR: %s: no valid device tree found\n", __func__);
30 return 0;
31 }
32
33 ret = fdt_check_header(fdt);
34 if (ret < 0) {
35 printf("fdt: %s\n", fdt_strerror(ret));
36 return 0;
37 }
38
39 node = fdt_path_offset(fdt, "/cavium,bdk");
40 if (node < 0) {
41 printf("%s: /cavium,bdk is missing from device tree: %s\n",
42 __func__, fdt_strerror(node));
43 return 0;
44 }
45 return node;
46 }
47
fdt_get_board_mac_addr(void)48 u64 fdt_get_board_mac_addr(void)
49 {
50 int node, len = 16;
51 const char *str = NULL;
52 const void *fdt = gd->fdt_blob;
53 u64 mac_addr = 0;
54
55 node = fdt_get_bdk_node();
56 if (!node)
57 return mac_addr;
58 str = fdt_getprop(fdt, node, "BOARD-MAC-ADDRESS", &len);
59 if (str)
60 mac_addr = simple_strtol(str, NULL, 16);
61 return mac_addr;
62 }
63
fdt_get_board_mac_cnt(void)64 int fdt_get_board_mac_cnt(void)
65 {
66 int node, len = 16;
67 const char *str = NULL;
68 const void *fdt = gd->fdt_blob;
69 int mac_count = 0;
70
71 node = fdt_get_bdk_node();
72 if (!node)
73 return mac_count;
74 str = fdt_getprop(fdt, node, "BOARD-MAC-ADDRESS-NUM", &len);
75 if (str) {
76 mac_count = simple_strtol(str, NULL, 10);
77 if (!mac_count)
78 mac_count = simple_strtol(str, NULL, 16);
79 debug("fdt: MAC_NUM %d\n", mac_count);
80 } else {
81 printf("Error: cannot retrieve mac count prop from fdt\n");
82 }
83 str = fdt_getprop(gd->fdt_blob, node, "BOARD-MAC-ADDRESS-NUM-OVERRIDE",
84 &len);
85 if (str) {
86 if (simple_strtol(str, NULL, 10) >= 0)
87 mac_count = simple_strtol(str, NULL, 10);
88 debug("fdt: MAC_NUM %d\n", mac_count);
89 } else {
90 printf("Error: cannot retrieve mac num override prop\n");
91 }
92 return mac_count;
93 }
94
fdt_get_board_serial(void)95 const char *fdt_get_board_serial(void)
96 {
97 const void *fdt = gd->fdt_blob;
98 int node, len = 64;
99 const char *str = NULL;
100
101 node = fdt_get_bdk_node();
102 if (!node)
103 return NULL;
104
105 str = fdt_getprop(fdt, node, "BOARD-SERIAL", &len);
106 if (!str)
107 printf("Error: cannot retrieve board serial from fdt\n");
108 return str;
109 }
110
fdt_get_board_revision(void)111 const char *fdt_get_board_revision(void)
112 {
113 const void *fdt = gd->fdt_blob;
114 int node, len = 64;
115 const char *str = NULL;
116
117 node = fdt_get_bdk_node();
118 if (!node)
119 return NULL;
120
121 str = fdt_getprop(fdt, node, "BOARD-REVISION", &len);
122 if (!str)
123 printf("Error: cannot retrieve board revision from fdt\n");
124 return str;
125 }
126
fdt_get_board_model(void)127 const char *fdt_get_board_model(void)
128 {
129 int node, len = 16;
130 const char *str = NULL;
131 const void *fdt = gd->fdt_blob;
132
133 node = fdt_get_bdk_node();
134 if (!node)
135 return NULL;
136 str = fdt_getprop(fdt, node, "BOARD-MODEL", &len);
137 if (!str)
138 printf("Error: cannot retrieve board model from fdt\n");
139 return str;
140 }
141
arch_fixup_memory_node(void * blob)142 int arch_fixup_memory_node(void *blob)
143 {
144 return 0;
145 }
146
ft_board_setup(void * blob,struct bd_info * bd)147 int ft_board_setup(void *blob, struct bd_info *bd)
148 {
149 int nodeoff, node, ret, i;
150 const char *temp;
151
152 static const char * const
153 octeontx_brd_nodes[] = {"BOARD-MODEL",
154 "BOARD-SERIAL",
155 "BOARD-MAC-ADDRESS",
156 "BOARD-REVISION",
157 "BOARD-MAC-ADDRESS-NUM"
158 };
159 char nodes[ARRAY_SIZE(octeontx_brd_nodes)][32];
160
161 ret = fdt_check_header(blob);
162 if (ret < 0) {
163 printf("ERROR: %s\n", fdt_strerror(ret));
164 return ret;
165 }
166
167 if (blob) {
168 nodeoff = fdt_path_offset(blob, "/cavium,bdk");
169 if (nodeoff < 0) {
170 printf("ERROR: FDT BDK node not found\n");
171 return nodeoff;
172 }
173
174 /* Read properties in temporary variables */
175 for (i = 0; i < ARRAY_SIZE(octeontx_brd_nodes); i++) {
176 temp = fdt_getprop(blob, nodeoff,
177 octeontx_brd_nodes[i], NULL);
178 strncpy(nodes[i], temp, sizeof(nodes[i]));
179 }
180
181 /* Delete cavium,bdk node */
182 ret = fdt_del_node(blob, nodeoff);
183 if (ret < 0) {
184 printf("WARNING : could not remove cavium, bdk node\n");
185 return ret;
186 }
187 debug("%s deleted 'cavium,bdk' node\n", __func__);
188 /*
189 * Add a new node at root level which would have
190 * necessary info
191 */
192 node = fdt_add_subnode(blob, 0, "octeontx_brd");
193 if (node < 0) {
194 printf("Cannot create node octeontx_brd: %s\n",
195 fdt_strerror(node));
196 return -EIO;
197 }
198
199 /* Populate properties in node */
200 for (i = 0; i < ARRAY_SIZE(octeontx_brd_nodes); i++) {
201 if (fdt_setprop_string(blob, node,
202 octeontx_brd_nodes[i],
203 nodes[i])) {
204 printf("Can't set %s\n", nodes[i]);
205 return -EIO;
206 }
207 }
208 }
209
210 return 0;
211 }
212
213 /**
214 * Return the FDT base address that was passed by ATF
215 *
216 * @return FDT base address received from ATF in x1 register
217 */
board_fdt_blob_setup(void)218 void *board_fdt_blob_setup(void)
219 {
220 return (void *)fdt_base_addr;
221 }
222