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