]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
98898625 SW |
2 | /* |
3 | * Copyright (c) 2010-2016, NVIDIA CORPORATION. | |
98898625 SW |
4 | */ |
5 | ||
d678a59d | 6 | #include <common.h> |
77409c7f TR |
7 | #include <fdtdec.h> |
8 | #include <stdlib.h> | |
9 | #include <asm/arch-tegra/cboot.h> | |
98898625 SW |
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 | */ | |
b75d8dc5 | 16 | int ft_system_setup(void *blob, struct bd_info *bd) |
98898625 SW |
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 | } | |
77409c7f TR |
37 | |
38 | #if defined(CONFIG_ARM64) | |
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 | ||
79 | static int ft_copy_carveout(void *dst, const void *src, const char *node) | |
80 | { | |
a0ba216e | 81 | const char *names = "memory-region-names"; |
77409c7f TR |
82 | struct fdt_memory carveout; |
83 | unsigned int index = 0; | |
a0ba216e TR |
84 | int err, offset, len; |
85 | const void *prop; | |
77409c7f TR |
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); | |
a0ba216e TR |
101 | else |
102 | break; | |
77409c7f TR |
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 | ||
a0ba216e TR |
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 | ||
77409c7f TR |
158 | return 0; |
159 | } | |
160 | ||
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 |