ARM: tegra: Refactor DT update helpers
[platform/kernel/u-boot.git] / arch / arm / mach-tegra / dt-setup.c
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  */
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)
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 {
81         struct fdt_memory carveout;
82         unsigned int index = 0;
83         int err;
84
85         while (true) {
86                 const char **compatibles = NULL;
87                 unsigned int num_compatibles;
88                 unsigned long flags;
89                 char *copy = NULL;
90                 const char *name;
91
92                 err = fdtdec_get_carveout(src, node, "memory-region", index,
93                                           &carveout, &name, &compatibles,
94                                           &num_compatibles, &flags);
95                 if (err < 0) {
96                         if (err != -FDT_ERR_NOTFOUND)
97                                 printf("failed to get carveout for %s: %d\n",
98                                        node, err);
99
100                         return err;
101                 }
102
103                 if (name) {
104                         const char *ptr = strchr(name, '@');
105
106                         if (ptr) {
107                                 copy = strndup(name, ptr - name);
108                                 name = copy;
109                         }
110                 } else {
111                         name = "carveout";
112                 }
113
114                 err = fdtdec_set_carveout(dst, node, "memory-region", index,
115                                           &carveout, name, compatibles,
116                                           num_compatibles, flags);
117                 if (err < 0) {
118                         printf("failed to set carveout for %s: %d\n", node,
119                                err);
120                         return err;
121                 }
122
123                 if (copy)
124                         free(copy);
125
126                 index++;
127         }
128
129         return 0;
130 }
131
132 void ft_carveout_setup(void *fdt, const char * const *nodes, unsigned int count)
133 {
134         const void *cboot_fdt = (const void *)cboot_boot_x0;
135         unsigned int i;
136         int err;
137
138         for (i = 0; i < count; i++) {
139                 printf("copying carveout for %s...\n", nodes[i]);
140
141                 err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
142                 if (err < 0) {
143                         if (err != -FDT_ERR_NOTFOUND)
144                                 printf("failed to copy carveout for %s: %d\n",
145                                        nodes[i], err);
146
147                         continue;
148                 }
149         }
150 }
151 #endif