1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2010-2016, NVIDIA CORPORATION.
4  */
5 
6 #include <common.h>
7 #include <fdtdec.h>
8 #include <stdlib.h>
9 #include <asm/arch-tegra/cboot.h>
10 #include <asm/arch-tegra/gpu.h>
11 
12 /*
13  * This function is called right before the kernel is booted. "blob" is the
14  * device tree that will be passed to the kernel.
15  */
ft_system_setup(void * blob,struct bd_info * bd)16 int ft_system_setup(void *blob, struct bd_info *bd)
17 {
18 	const char *gpu_compats[] = {
19 #if defined(CONFIG_TEGRA124)
20 		"nvidia,gk20a",
21 #endif
22 #if defined(CONFIG_TEGRA210)
23 		"nvidia,gm20b",
24 #endif
25 	};
26 	int i, ret;
27 
28 	/* Enable GPU node if GPU setup has been performed */
29 	for (i = 0; i < ARRAY_SIZE(gpu_compats); i++) {
30 		ret = tegra_gpu_enable_node(blob, gpu_compats[i]);
31 		if (ret)
32 			return ret;
33 	}
34 
35 	return 0;
36 }
37 
38 #if defined(CONFIG_ARM64)
ft_mac_address_setup(void * fdt)39 void ft_mac_address_setup(void *fdt)
40 {
41 	const void *cboot_fdt = (const void *)cboot_boot_x0;
42 	uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN];
43 	const char *path;
44 	int offset, err;
45 
46 	err = cboot_get_ethaddr(cboot_fdt, local_mac);
47 	if (err < 0)
48 		memset(local_mac, 0, ETH_ALEN);
49 
50 	path = fdt_get_alias(fdt, "ethernet");
51 	if (!path)
52 		return;
53 
54 	debug("ethernet alias found: %s\n", path);
55 
56 	offset = fdt_path_offset(fdt, path);
57 	if (offset < 0) {
58 		printf("ethernet alias points to absent node %s\n", path);
59 		return;
60 	}
61 
62 	if (is_valid_ethaddr(local_mac)) {
63 		err = fdt_setprop(fdt, offset, "local-mac-address", local_mac,
64 				  ETH_ALEN);
65 		if (!err)
66 			debug("Local MAC address set: %pM\n", local_mac);
67 	}
68 
69 	if (eth_env_get_enetaddr("ethaddr", mac)) {
70 		if (memcmp(local_mac, mac, ETH_ALEN) != 0) {
71 			err = fdt_setprop(fdt, offset, "mac-address", mac,
72 					  ETH_ALEN);
73 			if (!err)
74 				debug("MAC address set: %pM\n", mac);
75 		}
76 	}
77 }
78 
ft_copy_carveout(void * dst,const void * src,const char * node)79 static int ft_copy_carveout(void *dst, const void *src, const char *node)
80 {
81 	const char *names = "memory-region-names";
82 	struct fdt_memory carveout;
83 	unsigned int index = 0;
84 	int err, offset, len;
85 	const void *prop;
86 
87 	while (true) {
88 		const char **compatibles = NULL;
89 		unsigned int num_compatibles;
90 		unsigned long flags;
91 		char *copy = NULL;
92 		const char *name;
93 
94 		err = fdtdec_get_carveout(src, node, "memory-region", index,
95 					  &carveout, &name, &compatibles,
96 					  &num_compatibles, &flags);
97 		if (err < 0) {
98 			if (err != -FDT_ERR_NOTFOUND)
99 				printf("failed to get carveout for %s: %d\n",
100 				       node, err);
101 			else
102 				break;
103 
104 			return err;
105 		}
106 
107 		if (name) {
108 			const char *ptr = strchr(name, '@');
109 
110 			if (ptr) {
111 				copy = strndup(name, ptr - name);
112 				name = copy;
113 			}
114 		} else {
115 			name = "carveout";
116 		}
117 
118 		err = fdtdec_set_carveout(dst, node, "memory-region", index,
119 					  &carveout, name, compatibles,
120 					  num_compatibles, flags);
121 		if (err < 0) {
122 			printf("failed to set carveout for %s: %d\n", node,
123 			       err);
124 			return err;
125 		}
126 
127 		if (copy)
128 			free(copy);
129 
130 		index++;
131 	}
132 
133 	offset = fdt_path_offset(src, node);
134 	if (offset < 0) {
135 		debug("failed to find source offset for %s: %s\n", node,
136 		      fdt_strerror(err));
137 		return err;
138 	}
139 
140 	prop = fdt_getprop(src, offset, names, &len);
141 	if (prop) {
142 		offset = fdt_path_offset(dst, node);
143 		if (offset < 0) {
144 			debug("failed to find destination offset for %s: %s\n",
145 			      node, fdt_strerror(err));
146 			return err;
147 		}
148 
149 		err = fdt_setprop(dst, offset, "memory-region-names", prop,
150 				  len);
151 		if (err < 0) {
152 			debug("failed to copy \"%s\" property: %s\n", names,
153 			      fdt_strerror(err));
154 			return err;
155 		}
156 	}
157 
158 	return 0;
159 }
160 
ft_carveout_setup(void * fdt,const char * const * nodes,unsigned int count)161 void ft_carveout_setup(void *fdt, const char * const *nodes, unsigned int count)
162 {
163 	const void *cboot_fdt = (const void *)cboot_boot_x0;
164 	unsigned int i;
165 	int err;
166 
167 	for (i = 0; i < count; i++) {
168 		printf("copying carveout for %s...\n", nodes[i]);
169 
170 		err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
171 		if (err < 0) {
172 			if (err != -FDT_ERR_NOTFOUND)
173 				printf("failed to copy carveout for %s: %d\n",
174 				       nodes[i], err);
175 
176 			continue;
177 		}
178 	}
179 }
180 #endif
181