Merge tag 'u-boot-imx-20200825' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[platform/kernel/u-boot.git] / board / Marvell / octeontx / board-fdt.c
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 <env.h>
10 #include <log.h>
11 #include <net.h>
12 #include <asm/io.h>
13 #include <linux/compiler.h>
14 #include <linux/libfdt.h>
15 #include <fdtdec.h>
16 #include <fdt_support.h>
17 #include <asm/arch/board.h>
18 #include <asm/global_data.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 static int fdt_get_mdio_bus(const void *fdt, int phy_offset)
23 {
24         int node, bus = -1;
25         const u64 *reg;
26         u64 addr;
27
28         if (phy_offset < 0)
29                 return -1;
30         /* obtain mdio node and get the reg prop */
31         node = fdt_parent_offset(fdt, phy_offset);
32         if (node < 0)
33                 return -1;
34
35         reg = fdt_getprop(fdt, node, "reg", NULL);
36         addr = fdt64_to_cpu(*reg);
37         bus = (addr & (1 << 7)) ? 1 : 0;
38         return bus;
39 }
40
41 static int fdt_get_phy_addr(const void *fdt, int phy_offset)
42 {
43         const u32 *reg;
44         int addr = -1;
45
46         if (phy_offset < 0)
47                 return -1;
48         reg = fdt_getprop(fdt, phy_offset, "reg", NULL);
49         addr = fdt32_to_cpu(*reg);
50         return addr;
51 }
52
53 void fdt_parse_phy_info(void)
54 {
55         const void *fdt = gd->fdt_blob;
56         int offset = 0, node, bgx_id = 0, lmacid = 0;
57         const u32 *val;
58         char bgxname[24];
59         int len, rgx_id = 0, eth_id = 0;
60         int phandle, phy_offset;
61         int subnode, i;
62         int bdknode;
63
64         bdknode = fdt_path_offset(fdt, "/cavium,bdk");
65         if (bdknode < 0) {
66                 printf("%s: bdk node is missing from device tree: %s\n",
67                        __func__, fdt_strerror(bdknode));
68         }
69
70         offset = fdt_node_offset_by_compatible(fdt, -1, "pci-bridge");
71         if (offset < 1)
72                 return;
73
74         for (bgx_id = 0; bgx_id < MAX_BGX_PER_NODE; bgx_id++) {
75                 int phy_addr[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = -1};
76                 bool autoneg_dis[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0};
77                 int mdio_bus[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = -1};
78                 bool lmac_reg[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0};
79                 bool lmac_enable[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0};
80
81                 snprintf(bgxname, sizeof(bgxname), "bgx%d", bgx_id);
82                 node = fdt_subnode_offset(fdt, offset, bgxname);
83                 if (node < 0) {
84                         /* check if it is rgx node */
85                         snprintf(bgxname, sizeof(bgxname), "rgx%d", rgx_id);
86                         node = fdt_subnode_offset(fdt, offset, bgxname);
87                         if (node < 0) {
88                                 debug("bgx%d/rgx0 node not found\n", bgx_id);
89                                 return;
90                         }
91                 }
92                 debug("bgx%d node found\n", bgx_id);
93
94                 /*
95                  * loop through each of the bgx/rgx nodes
96                  * to find PHY nodes
97                  */
98                 fdt_for_each_subnode(subnode, fdt, node) {
99                         /* Check for reg property */
100                         val = fdt_getprop(fdt, subnode, "reg", &len);
101                         if (val) {
102                                 debug("lmacid = %d\n", lmacid);
103                                 lmac_reg[lmacid] = 1;
104                         }
105                         /* check for phy-handle property */
106                         val = fdt_getprop(fdt, subnode, "phy-handle", &len);
107                         if (val) {
108                                 phandle = fdt32_to_cpu(*val);
109                                 if (!phandle) {
110                                         debug("phandle not valid %d\n", lmacid);
111                                 } else {
112                                         phy_offset = fdt_node_offset_by_phandle
113                                                         (fdt, phandle);
114                                         phy_addr[lmacid] = fdt_get_phy_addr
115                                                         (fdt, phy_offset);
116                                         mdio_bus[lmacid] = fdt_get_mdio_bus
117                                                         (fdt, phy_offset);
118                                         }
119                                 } else {
120                                         debug("phy-handle prop not found %d\n",
121                                               lmacid);
122                                 }
123                                 /* check for autonegotiation property */
124                                 val = fdt_getprop(fdt, subnode,
125                                                   "cavium,disable-autonegotiation",
126                                                   &len);
127                                 if (val)
128                                         autoneg_dis[lmacid] = 1;
129
130                                 eth_id++;
131                                 lmacid++;
132                         }
133
134                         for (i = 0; i < MAX_LMAC_PER_BGX; i++) {
135                                 const char *str;
136
137                                 snprintf(bgxname, sizeof(bgxname),
138                                          "BGX-ENABLE.N0.BGX%d.P%d", bgx_id, i);
139                                 if (bdknode >= 0) {
140                                         str = fdt_getprop(fdt, bdknode,
141                                                           bgxname, &len);
142                                         if (str)
143                                                 lmac_enable[i] =
144                                                         simple_strtol(str, NULL,
145                                                                       10);
146                                 }
147                         }
148
149                         lmacid = 0;
150                         bgx_set_board_info(bgx_id, mdio_bus, phy_addr,
151                                            autoneg_dis, lmac_reg, lmac_enable);
152                 }
153 }
154
155 static int fdt_get_bdk_node(void)
156 {
157         int node, ret;
158         const void *fdt = gd->fdt_blob;
159
160         if (!fdt) {
161                 printf("ERROR: %s: no valid device tree found\n", __func__);
162                 return 0;
163         }
164
165         ret = fdt_check_header(fdt);
166         if (ret < 0) {
167                 printf("fdt: %s\n", fdt_strerror(ret));
168                 return 0;
169         }
170
171         node = fdt_path_offset(fdt, "/cavium,bdk");
172         if (node < 0) {
173                 printf("%s: /cavium,bdk is missing from device tree: %s\n",
174                        __func__, fdt_strerror(node));
175                 return 0;
176         }
177         return node;
178 }
179
180 const char *fdt_get_board_serial(void)
181 {
182         const void *fdt = gd->fdt_blob;
183         int node, len = 64;
184         const char *str = NULL;
185
186         node = fdt_get_bdk_node();
187         if (!node)
188                 return NULL;
189
190         str = fdt_getprop(fdt, node, "BOARD-SERIAL", &len);
191         if (!str)
192                 printf("Error: cannot retrieve board serial from fdt\n");
193         return str;
194 }
195
196 const char *fdt_get_board_revision(void)
197 {
198         const void *fdt = gd->fdt_blob;
199         int node, len = 64;
200         const char *str = NULL;
201
202         node = fdt_get_bdk_node();
203         if (!node)
204                 return NULL;
205
206         str = fdt_getprop(fdt, node, "BOARD-REVISION", &len);
207         if (!str)
208                 printf("Error: cannot retrieve board revision from fdt\n");
209         return str;
210 }
211
212 const char *fdt_get_board_model(void)
213 {
214         const void *fdt = gd->fdt_blob;
215         int node, len = 16;
216         const char *str = NULL;
217
218         node = fdt_get_bdk_node();
219         if (!node)
220                 return NULL;
221
222         str = fdt_getprop(fdt, node, "BOARD-MODEL", &len);
223         if (!str)
224                 printf("Error: cannot retrieve board model from fdt\n");
225         return str;
226 }
227
228 void fdt_board_get_ethaddr(int bgx, int lmac, unsigned char *eth)
229 {
230         const void *fdt = gd->fdt_blob;
231         const char *mac = NULL;
232         int offset = 0, node, len;
233         int subnode, i = 0;
234         char bgxname[24];
235
236         offset = fdt_node_offset_by_compatible(fdt, -1, "pci-bridge");
237         if (offset < 0) {
238                 printf("%s couldn't find mrml bridge node in fdt\n",
239                        __func__);
240                 return;
241         }
242         if (bgx == 2 && otx_is_soc(CN81XX)) {
243                 snprintf(bgxname, sizeof(bgxname), "rgx%d", 0);
244                 lmac = 0;
245         } else {
246                 snprintf(bgxname, sizeof(bgxname), "bgx%d", bgx);
247         }
248
249         node = fdt_subnode_offset(fdt, offset, bgxname);
250
251         fdt_for_each_subnode(subnode, fdt, node) {
252                 if (i++ != lmac)
253                         continue;
254                 /* check for local-mac-address */
255                 mac = fdt_getprop(fdt, subnode, "local-mac-address", &len);
256                 if (mac) {
257                         debug("%s mac %pM\n", __func__, mac);
258                         memcpy(eth, mac, ARP_HLEN);
259                 } else {
260                         memset(eth, 0, ARP_HLEN);
261                 }
262                 debug("%s eth %pM\n", __func__, eth);
263                 return;
264         }
265 }
266
267 int arch_fixup_memory_node(void *blob)
268 {
269         return 0;
270 }
271
272 int ft_board_setup(void *blob, struct bd_info *bd)
273 {
274         /* remove "cavium, bdk" node from DT */
275         int ret = 0, offset;
276
277         ret = fdt_check_header(blob);
278         if (ret < 0) {
279                 printf("ERROR: %s\n", fdt_strerror(ret));
280                 return ret;
281         }
282
283         if (blob) {
284                 offset = fdt_path_offset(blob, "/cavium,bdk");
285                 if (offset < 0) {
286                         printf("ERROR: FDT BDK node not found\n");
287                         return offset;
288                 }
289
290                 /* delete node */
291                 ret = fdt_del_node(blob, offset);
292                 if (ret < 0) {
293                         printf("WARNING : could not remove bdk node\n");
294                         return ret;
295                 }
296
297                 debug("%s deleted bdk node\n", __func__);
298         }
299
300         return 0;
301 }
302
303 /**
304  * Return the FDT base address that was passed by ATF
305  *
306  * @return      FDT base address received from ATF in x1 register
307  */
308 void *board_fdt_blob_setup(void)
309 {
310         return (void *)fdt_base_addr;
311 }