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 21DECLARE_GLOBAL_DATA_PTR; 22 23static 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 48u64 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 64int 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 95const 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 111const 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 127const 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 142int arch_fixup_memory_node(void *blob) 143{ 144 return 0; 145} 146 147int 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 */ 218void *board_fdt_blob_setup(int *err) 219{ 220 *err = 0; 221 return (void *)fdt_base_addr; 222} 223