blob: d581326399a90d7685dce9315a7789be4dc72aaf [file] [log] [blame]
Channagoud Kadabi571193a2014-02-05 13:58:49 -08001/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <libfdt.h>
30#include <dev_tree.h>
31#include <lib/ptable.h>
32#include <malloc.h>
33#include <qpic_nand.h>
34#include <stdlib.h>
35#include <string.h>
36#include <platform.h>
37#include <board.h>
38
Joel Kingaa335dc2013-06-03 16:11:08 -070039struct dt_entry_v1
40{
41 uint32_t platform_id;
42 uint32_t variant_id;
43 uint32_t soc_rev;
44 uint32_t offset;
45 uint32_t size;
46};
47
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -070048static struct dt_mem_node_info mem_node;
49
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -070050static int platform_dt_match(struct dt_entry *cur_dt_entry, struct board_dt_entry *board_dt_data, uint32_t subtype_mask);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070051extern int target_is_emmc_boot(void);
52extern uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset);
Deepa Dinamanic55f01b2013-05-30 14:05:56 -070053/* TODO: This function needs to be moved to target layer to check violations
54 * against all the other regions as well.
55 */
56extern int check_aboot_addr_range_overlap(uint32_t start, uint32_t size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070057
Shashank Mittalc0f10282013-07-15 14:53:31 -070058/* Returns soc version if platform id and hardware id matches
59 otherwise return 0xFFFFFFFF */
60#define INVALID_SOC_REV_ID 0XFFFFFFFF
61static uint32_t dev_tree_compatible(void *dtb)
Dima Zavinc46f8382013-05-03 12:23:06 -070062{
63 int root_offset;
Channagoud Kadabia4dbe332013-09-05 17:44:11 -070064 const void *prop = NULL;
65 const char *plat_prop = NULL;
66 const char *board_prop = NULL;
67 char *model = NULL;
68 struct dt_entry cur_dt_entry;
69 struct dt_entry *dt_entry_v2 = NULL;
70 struct board_id *board_data = NULL;
71 struct plat_id *platform_data = NULL;
Dima Zavinc46f8382013-05-03 12:23:06 -070072 int len;
Channagoud Kadabia4dbe332013-09-05 17:44:11 -070073 int len_board_id;
74 int len_plat_id;
75 int min_plat_id_len = 0;
76 uint32_t target_variant_id;
77 uint32_t dtb_ver;
78 uint32_t num_entries = 0;
79 uint32_t i, j, k;
80 uint32_t found = 0;
81 uint32_t msm_data_count;
82 uint32_t board_data_count;
83 uint32_t soc_rev;
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -070084 struct board_dt_entry board_dt_data;
Dima Zavinc46f8382013-05-03 12:23:06 -070085
86 root_offset = fdt_path_offset(dtb, "/");
87 if (root_offset < 0)
88 return false;
89
90 prop = fdt_getprop(dtb, root_offset, "model", &len);
91 if (prop && len > 0) {
Channagoud Kadabia4dbe332013-09-05 17:44:11 -070092 model = (char *) malloc(sizeof(char) * len);
93 ASSERT(model);
94 strlcpy(model, prop, len);
Dima Zavinc46f8382013-05-03 12:23:06 -070095 } else {
vijay kumar89d36d82014-06-30 19:32:18 +053096 dprintf(INFO, "model does not exist in device tree\n");
Dima Zavinc46f8382013-05-03 12:23:06 -070097 }
98
Channagoud Kadabia4dbe332013-09-05 17:44:11 -070099 /* Find the board-id prop from DTB , if board-id is present then
100 * the DTB is version 2 */
101 board_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,board-id", &len_board_id);
vijay kumar89d36d82014-06-30 19:32:18 +0530102 if (board_prop && len_board_id > 0)
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700103 {
vijay kumar89d36d82014-06-30 19:32:18 +0530104 if (len_board_id % BOARD_ID_SIZE)
105 {
106 dprintf(CRITICAL, "qcom,board-id in device tree is (%d) not a multiple of (%d)\n",
107 len_board_id, BOARD_ID_SIZE);
108 return false;
109 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700110 dtb_ver = DEV_TREE_VERSION_V2;
111 min_plat_id_len = PLAT_ID_SIZE;
112 }
113 else
114 {
115 dtb_ver = DEV_TREE_VERSION_V1;
116 min_plat_id_len = DT_ENTRY_V1_SIZE;
117 }
118
119 /* Get the msm-id prop from DTB */
120 plat_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,msm-id", &len_plat_id);
121 if (!plat_prop || len_plat_id <= 0) {
Dima Zavinc46f8382013-05-03 12:23:06 -0700122 dprintf(INFO, "qcom,msm-id entry not found\n");
123 return false;
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700124 } else if (len_plat_id % min_plat_id_len) {
125 dprintf(INFO, "qcom,msm-id in device tree is (%d) not a multiple of (%d)\n",
126 len_plat_id, min_plat_id_len);
Dima Zavinc46f8382013-05-03 12:23:06 -0700127 return false;
128 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700129
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700130 /*
131 * If DTB version is '1' look for <x y z> pair in the DTB
132 * x: platform_id
133 * y: variant_id
134 * z: SOC rev
135 */
136 if (dtb_ver == DEV_TREE_VERSION_V1)
137 {
138 while (len_plat_id)
139 {
140 cur_dt_entry.platform_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->platform_id);
141 cur_dt_entry.variant_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->variant_id);
142 cur_dt_entry.soc_rev = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->soc_rev);
143 cur_dt_entry.board_hw_subtype = board_hardware_subtype();
Dima Zavinc46f8382013-05-03 12:23:06 -0700144
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700145 board_dt_data.target_variant_id = board_hardware_id();
146 board_dt_data.platform_variant_id = board_platform_id();
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700147
148 dprintf(SPEW, "Found an appended flattened device tree (%s - %u %u 0x%x)\n",
vijay kumar89d36d82014-06-30 19:32:18 +0530149 model ? model : "unknown",
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700150 cur_dt_entry.platform_id, cur_dt_entry.variant_id, cur_dt_entry.soc_rev);
151
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700152 if (platform_dt_match(&cur_dt_entry, &board_dt_data, 0) == 1)
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700153 {
154 dprintf(SPEW, "Device tree's msm_id doesn't match the board: <%u %u 0x%x> != <%u %u 0x%x>\n",
155 cur_dt_entry.platform_id,
156 cur_dt_entry.variant_id,
157 cur_dt_entry.soc_rev,
158 board_platform_id(),
159 board_hardware_id(),
160 board_soc_version());
161 plat_prop += DT_ENTRY_V1_SIZE;
162 len_plat_id -= DT_ENTRY_V1_SIZE;
163 continue;
164 }
165 else
166 {
167 found = 1;
168 break;
169 }
170 }
171 }
172 /*
173 * If DTB Version is '2' then we have split DTB with board & msm data
174 * populated saperately in board-id & msm-id prop respectively.
175 * Extract the data & prepare a look up table
176 */
177 else if (dtb_ver == DEV_TREE_VERSION_V2)
178 {
179 board_data_count = (len_board_id / BOARD_ID_SIZE);
180 msm_data_count = (len_plat_id / PLAT_ID_SIZE);
181
182 /* If we are using dtb v2.0, then we have split board & msm data in the DTB */
183 board_data = (struct board_id *) malloc(sizeof(struct board_id) * (len_board_id / BOARD_ID_SIZE));
184 ASSERT(board_data);
185 platform_data = (struct plat_id *) malloc(sizeof(struct plat_id) * (len_plat_id / PLAT_ID_SIZE));
186 ASSERT(platform_data);
187 i = 0;
188
189 /* Extract board data from DTB */
190 for(i = 0 ; i < board_data_count; i++)
191 {
192 board_data[i].variant_id = fdt32_to_cpu(((struct board_id *)board_prop)->variant_id);
193 board_data[i].platform_subtype = fdt32_to_cpu(((struct board_id *)board_prop)->platform_subtype);
194 len_board_id -= sizeof(struct board_id);
195 board_prop += sizeof(struct board_id);
196 }
197
198 /* Extract platform data from DTB */
199 for(i = 0 ; i < msm_data_count; i++)
200 {
201 platform_data[i].platform_id = fdt32_to_cpu(((struct plat_id *)plat_prop)->platform_id);
202 platform_data[i].soc_rev = fdt32_to_cpu(((struct plat_id *)plat_prop)->soc_rev);
203 len_plat_id -= sizeof(struct plat_id);
204 plat_prop += sizeof(struct plat_id);
205 }
206
207 /* We need to merge board & platform data into dt entry structure */
208 num_entries = msm_data_count * board_data_count;
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700209
vijay kumar89d36d82014-06-30 19:32:18 +0530210 if (((uint64_t)msm_data_count * (uint64_t)board_data_count) == msm_data_count * board_data_count) {
211 dt_entry_v2 = (struct dt_entry*) malloc(sizeof(struct dt_entry) * num_entries);
212 ASSERT(dt_entry_v2);
213
214 /* If we have '<X>; <Y>; <Z>' as platform data & '<A>; <B>; <C>' as board data.
215 * Then dt entry should look like
216 * <X ,A >;<X, B>;<X, C>;
217 * <Y ,A >;<Y, B>;<Y, C>;
218 * <Z ,A >;<Z, B>;<Z, C>;
219 */
220 i = 0;
221 k = 0;
222 for (i = 0; i < msm_data_count; i++)
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700223 {
vijay kumar89d36d82014-06-30 19:32:18 +0530224 for (j = 0; j < board_data_count; j++)
225 {
226 dt_entry_v2[k].platform_id = platform_data[i].platform_id;
227 dt_entry_v2[k].soc_rev = platform_data[i].soc_rev;
228 dt_entry_v2[k].variant_id = board_data[j].variant_id;
229 dt_entry_v2[k].board_hw_subtype = board_data[j].platform_subtype;
230 k++;
231 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700232 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700233
vijay kumar89d36d82014-06-30 19:32:18 +0530234 /* Now find the matching entry in the merged list */
235 if (board_hardware_id() == HW_PLATFORM_QRD)
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700236 {
vijay kumar89d36d82014-06-30 19:32:18 +0530237 board_dt_data.target_variant_id = board_target_id();
238 board_dt_data.platform_variant_id = board_platform_id();
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700239 }
240 else
241 {
vijay kumar89d36d82014-06-30 19:32:18 +0530242 board_dt_data.target_variant_id = board_hardware_id() | ((board_hardware_subtype() & 0xff) << 24);
243 board_dt_data.platform_variant_id = board_platform_id();
244 }
245
246 for (i=0 ;i < num_entries; i++)
247 {
248 dprintf(SPEW, "Found an appended flattened device tree (%s - %u %u %u 0x%x)\n",
249 *model ? model : "unknown",
250 dt_entry_v2[i].platform_id, dt_entry_v2[i].variant_id, dt_entry_v2[i].board_hw_subtype, dt_entry_v2[i].soc_rev);
251
252 if (platform_dt_match(&dt_entry_v2[i], &board_dt_data, 0xff) == 1)
253 {
254 dprintf(SPEW, "Device tree's msm_id doesn't match the board: <%u %u %u 0x%x> != <%u %u %u 0x%x>\n",
255 dt_entry_v2[i].platform_id,
256 dt_entry_v2[i].variant_id,
257 dt_entry_v2[i].soc_rev,
258 dt_entry_v2[i].board_hw_subtype,
259 board_platform_id(),
260 board_hardware_id(),
261 board_hardware_subtype(),
262 board_soc_version());
263 continue;
264 }
265 else
266 {
267 /* If found a match, return the cur_dt_entry */
268 found = 1;
269 cur_dt_entry = dt_entry_v2[i];
270 break;
271 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700272 }
273 }
vijay kumar89d36d82014-06-30 19:32:18 +0530274 else
275 dprintf(CRITICAL, "Device tree got corrupted\n");
Dima Zavinc46f8382013-05-03 12:23:06 -0700276 }
277
vijay kumar89d36d82014-06-30 19:32:18 +0530278 if (dtb_ver == DEV_TREE_VERSION_V1)
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700279 {
vijay kumar89d36d82014-06-30 19:32:18 +0530280 if (!found)
281 soc_rev = INVALID_SOC_REV_ID;
282 else
283 {
284 soc_rev = cur_dt_entry.soc_rev;
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700285
vijay kumar89d36d82014-06-30 19:32:18 +0530286 dprintf(INFO, "Device tree's msm_id matches the board: <%u %u %u 0x%x> == <%u %u %u 0x%x>\n",
287 cur_dt_entry.platform_id,
288 cur_dt_entry.variant_id,
289 cur_dt_entry.board_hw_subtype,
290 cur_dt_entry.soc_rev,
291 board_platform_id(),
292 board_hardware_id(),
293 board_hardware_subtype(),
294 board_soc_version());
295 }
296 return soc_rev;
297 }
298 else if (dtb_ver == DEV_TREE_VERSION_V2)
299 {
300 if (!found)
301 {
302 soc_rev = INVALID_SOC_REV_ID;
303 goto end;
304 }
305 else
306 soc_rev = cur_dt_entry.soc_rev;
307
308 dprintf(INFO, "Device tree's msm_id matches the board: <%u %u %u 0x%x> == <%u %u %u 0x%x>\n",
309 cur_dt_entry.platform_id,
310 cur_dt_entry.variant_id,
311 cur_dt_entry.board_hw_subtype,
312 cur_dt_entry.soc_rev,
313 board_platform_id(),
314 board_hardware_id(),
315 board_hardware_subtype(),
316 board_soc_version());
317 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700318
319end:
320 free(board_data);
321 free(platform_data);
322 free(dt_entry_v2);
vijay kumar89d36d82014-06-30 19:32:18 +0530323 if(model) {
324 free(model);
325 }
Channagoud Kadabia4dbe332013-09-05 17:44:11 -0700326 return soc_rev;
Dima Zavinc46f8382013-05-03 12:23:06 -0700327}
328
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800329/*
Dima Zavin77e41f32013-03-06 16:10:43 -0800330 * Will relocate the DTB to the tags addr if the device tree is found and return
331 * its address
332 *
333 * Arguments: kernel - Start address of the kernel loaded in RAM
334 * tags - Start address of the tags loaded in RAM
Channagoud Kadabi704cd562013-04-25 15:19:59 -0700335 * kernel_size - Size of the kernel in bytes
336 *
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800337 * Return Value: DTB address : If appended device tree is found
Dima Zavin77e41f32013-03-06 16:10:43 -0800338 * 'NULL' : Otherwise
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800339 */
Dima Zavinc46f8382013-05-03 12:23:06 -0700340void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags)
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800341{
Dima Zavinc46f8382013-05-03 12:23:06 -0700342 void *kernel_end = kernel + kernel_size;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800343 uint32_t app_dtb_offset = 0;
Dima Zavinc46f8382013-05-03 12:23:06 -0700344 void *dtb;
Shashank Mittalc0f10282013-07-15 14:53:31 -0700345 void *bestmatch_tag = NULL;
346 uint32_t bestmatch_tag_size;
347 uint32_t bestmatch_soc_rev_id = INVALID_SOC_REV_ID;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800348
349 memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800350
vijay kumare2a5ea82014-06-25 12:24:14 +0530351 if (((uintptr_t)kernel + (uintptr_t)app_dtb_offset) < (uintptr_t)kernel) {
352 return NULL;
353 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700354 dtb = kernel + app_dtb_offset;
vijay kumare2a5ea82014-06-25 12:24:14 +0530355 while (((uintptr_t)dtb + sizeof(struct fdt_header)) < (uintptr_t)kernel_end) {
Shashank Mittalc0f10282013-07-15 14:53:31 -0700356 uint32_t dtb_soc_rev_id;
Dima Zavinc46f8382013-05-03 12:23:06 -0700357 struct fdt_header dtb_hdr;
358 uint32_t dtb_size;
Dima Zavin77e41f32013-03-06 16:10:43 -0800359
Dima Zavinc46f8382013-05-03 12:23:06 -0700360 /* the DTB could be unaligned, so extract the header,
361 * and operate on it separately */
362 memcpy(&dtb_hdr, dtb, sizeof(struct fdt_header));
363 if (fdt_check_header((const void *)&dtb_hdr) != 0 ||
vijay kumare2a5ea82014-06-25 12:24:14 +0530364 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const void *)&dtb_hdr) < (uintptr_t)dtb) ||
365 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const void *)&dtb_hdr) > (uintptr_t)kernel_end))
Dima Zavinc46f8382013-05-03 12:23:06 -0700366 break;
367 dtb_size = fdt_totalsize(&dtb_hdr);
368
vijay kumarb05eed22014-06-24 16:30:18 +0530369 if (check_aboot_addr_range_overlap(tags, dtb_size)) {
370 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
371 return NULL;
372 }
373
Dima Zavinc46f8382013-05-03 12:23:06 -0700374 /* now that we know we have a valid DTB, we need to copy
375 * it somewhere aligned, like tags */
376 memcpy(tags, dtb, dtb_size);
377
Shashank Mittalc0f10282013-07-15 14:53:31 -0700378 dtb_soc_rev_id = dev_tree_compatible(tags);
379 if (dtb_soc_rev_id == board_soc_version()) {
Dima Zavinc46f8382013-05-03 12:23:06 -0700380 /* clear out the old DTB magic so kernel doesn't find it */
381 *((uint32_t *)(kernel + app_dtb_offset)) = 0;
382 return tags;
Shashank Mittalc0f10282013-07-15 14:53:31 -0700383 } else if ((dtb_soc_rev_id != INVALID_SOC_REV_ID) &&
384 (dtb_soc_rev_id < board_soc_version())) {
385 /* if current bestmatch is less than new dtb_soc_rev_id then update
386 bestmatch_tag */
387 if((bestmatch_soc_rev_id == INVALID_SOC_REV_ID) ||
388 (bestmatch_soc_rev_id < dtb_soc_rev_id)) {
389 bestmatch_tag = dtb;
390 bestmatch_tag_size = dtb_size;
391 bestmatch_soc_rev_id = dtb_soc_rev_id;
392 }
Dima Zavin77e41f32013-03-06 16:10:43 -0800393 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700394
395 /* goto the next device tree if any */
396 dtb += dtb_size;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800397 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700398
Shashank Mittalc0f10282013-07-15 14:53:31 -0700399 if(bestmatch_tag) {
400 dprintf(INFO,"DTB found with bestmatch soc rev id 0x%x.Board soc rev id 0x%x\n",
401 bestmatch_soc_rev_id, board_soc_version());
402 memcpy(tags, bestmatch_tag, bestmatch_tag_size);
403 /* clear out the old DTB magic so kernel doesn't find it */
404 *((uint32_t *)(kernel + app_dtb_offset)) = 0;
405 return tags;
406 }
407
Dima Zavinc46f8382013-05-03 12:23:06 -0700408 dprintf(CRITICAL, "DTB offset is incorrect, kernel image does not have appended DTB\n");
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800409
Dima Zavin77e41f32013-03-06 16:10:43 -0800410 return NULL;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800411}
412
Joel Kingaa335dc2013-06-03 16:11:08 -0700413/* Returns 0 if the device tree is valid. */
Deepa Dinamani87252952013-09-09 13:58:27 -0700414int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size)
Joel Kingaa335dc2013-06-03 16:11:08 -0700415{
416 int dt_entry_size;
Channagoud Kadabid87c2772014-06-20 15:41:55 -0700417 uint64_t hdr_size;
Joel Kingaa335dc2013-06-03 16:11:08 -0700418
419 /* Validate the device tree table header */
420 if(table->magic != DEV_TREE_MAGIC) {
421 dprintf(CRITICAL, "ERROR: Bad magic in device tree table \n");
422 return -1;
423 }
424
425 if (table->version == DEV_TREE_VERSION_V1) {
426 dt_entry_size = sizeof(struct dt_entry_v1);
427 } else if (table->version == DEV_TREE_VERSION_V2) {
428 dt_entry_size = sizeof(struct dt_entry);
429 } else {
430 dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n",
431 table->version);
432 return -1;
433 }
434
Channagoud Kadabid87c2772014-06-20 15:41:55 -0700435 hdr_size = (uint64_t)table->num_entries * dt_entry_size + DEV_TREE_HEADER_SIZE;
436
Deepa Dinamani87252952013-09-09 13:58:27 -0700437 /* Roundup to page_size. */
438 hdr_size = ROUNDUP(hdr_size, page_size);
439
Channagoud Kadabid87c2772014-06-20 15:41:55 -0700440 if (hdr_size > UINT_MAX)
441 return -1;
442 else
443 *dt_hdr_size = hdr_size & UINT_MAX;
Joel Kingaa335dc2013-06-03 16:11:08 -0700444
445 return 0;
446}
447
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700448static int platform_dt_match(struct dt_entry *cur_dt_entry, struct board_dt_entry *board_dt_data, uint32_t subtype_mask)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700449{
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800450 /*
451 * 1. Check if cur_dt_entry has platform_hw_version major & minor present?
452 * 2. If present, calculate cur_dt_target_id for the current platform as:
453 * 3. bit no |31 24 | 23 16| 15 8 |7 0|
454 * 4. |subtype| major | minor |hw_platform|
455 */
456 uint32_t cur_dt_target_id ;
Aparna Mallavarapu6eb30902014-05-13 17:03:10 +0530457 uint32_t cur_dt_hlos_subtype;
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800458
459 /*
460 * if variant_id has platform_hw_ver has major = 0xff and minor = 0xff,
461 * ignore the major & minor versions from the DTB entry
462 */
463 if ((cur_dt_entry->variant_id & 0xffff00) == 0xffff00)
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700464 cur_dt_target_id = (cur_dt_entry->variant_id & 0xff0000ff) | (board_dt_data->target_variant_id & 0xffff00);
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800465 /*
466 * We have a valid platform_hw_version major & minor numbers in the board-id, so
467 * use the board-id from the DTB.
468 * Note: For some QRD platforms the format used is qcom, board-id = <0xMVmVPT 0xPS>
469 * where: MV: platform major ver, mV: platform minor ver, PT: platform type
470 * PS: platform subtype, so we need to put PS @ bit 24-31 to be backward compatible.
471 */
472 else
473 cur_dt_target_id = cur_dt_entry->variant_id | ((cur_dt_entry->board_hw_subtype & subtype_mask & 0xff) << 24);
Aparna Mallavarapu6eb30902014-05-13 17:03:10 +0530474 /* Determine the bits 23:8 to check the DT with the DDR Size */
475 cur_dt_hlos_subtype = (cur_dt_entry->board_hw_subtype & 0xffff00);
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800476
477 /* 1. must match the platform_id, platform_hw_id, platform_version
Maria Yu2e2d2c22013-07-03 19:20:33 +0800478 * 2. soc rev number equal then return 0
479 * 3. dt soc rev number less than cdt return -1
480 * 4. otherwise return 1
481 */
Maria Yu2e2d2c22013-07-03 19:20:33 +0800482
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700483 if((cur_dt_entry->platform_id == board_dt_data->platform_variant_id) &&
484 (cur_dt_target_id == board_dt_data->target_variant_id) &&
Aparna Mallavarapu6eb30902014-05-13 17:03:10 +0530485 (cur_dt_hlos_subtype == target_get_hlos_subtype())) {
Maria Yu2e2d2c22013-07-03 19:20:33 +0800486 if(cur_dt_entry->soc_rev == board_soc_version()) {
Maria Yuca51ee22013-06-27 21:45:24 +0800487 return 0;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800488 } else if(cur_dt_entry->soc_rev < board_soc_version()) {
489 return -1;
Maria Yuca51ee22013-06-27 21:45:24 +0800490 }
491 }
Maria Yuca51ee22013-06-27 21:45:24 +0800492
Maria Yu2e2d2c22013-07-03 19:20:33 +0800493 return 1;
Maria Yuca51ee22013-06-27 21:45:24 +0800494}
495
Maria Yu2e2d2c22013-07-03 19:20:33 +0800496static int __dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info,
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700497 struct board_dt_entry *board_dt_data, uint32_t subtype_mask)
Maria Yuca51ee22013-06-27 21:45:24 +0800498{
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700499 uint32_t i;
Joel Kingaa335dc2013-06-03 16:11:08 -0700500 unsigned char *table_ptr;
501 struct dt_entry dt_entry_buf_1;
502 struct dt_entry dt_entry_buf_2;
503 struct dt_entry *cur_dt_entry;
504 struct dt_entry *best_match_dt_entry;
505 struct dt_entry_v1 *dt_entry_v1;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800506 uint32_t found = 0;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700507
Joel Kingaa335dc2013-06-03 16:11:08 -0700508 if (!dt_entry_info) {
509 dprintf(CRITICAL, "ERROR: Bad parameter passed to %s \n",
510 __func__);
511 return -1;
512 }
513
514 table_ptr = (unsigned char *)table + DEV_TREE_HEADER_SIZE;
515 cur_dt_entry = &dt_entry_buf_1;
516 best_match_dt_entry = NULL;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700517
Maria Yu2e2d2c22013-07-03 19:20:33 +0800518 for(i = 0; found == 0 && i < table->num_entries; i++)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700519 {
Joel Kingaa335dc2013-06-03 16:11:08 -0700520 memset(cur_dt_entry, 0, sizeof(struct dt_entry));
521 switch(table->version) {
522 case DEV_TREE_VERSION_V1:
523 dt_entry_v1 = (struct dt_entry_v1 *)table_ptr;
524 cur_dt_entry->platform_id = dt_entry_v1->platform_id;
525 cur_dt_entry->variant_id = dt_entry_v1->variant_id;
526 cur_dt_entry->soc_rev = dt_entry_v1->soc_rev;
527 cur_dt_entry->board_hw_subtype = board_hardware_subtype();
528 cur_dt_entry->offset = dt_entry_v1->offset;
529 cur_dt_entry->size = dt_entry_v1->size;
530 table_ptr += sizeof(struct dt_entry_v1);
531 break;
532 case DEV_TREE_VERSION_V2:
533 memcpy(cur_dt_entry, (struct dt_entry *)table_ptr,
534 sizeof(struct dt_entry));
535 table_ptr += sizeof(struct dt_entry);
536 break;
537 default:
538 dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n",
539 table->version);
540 return -1;
541 }
542
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800543 /* DTBs are stored in the ascending order of soc revision.
544 * For eg: Rev0..Rev1..Rev2 & so on.
545 * we pickup the DTB with highest soc rev number which is less
546 * than or equal to actual hardware
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700547 */
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700548 switch(platform_dt_match(cur_dt_entry, board_dt_data, subtype_mask)) {
Maria Yu2e2d2c22013-07-03 19:20:33 +0800549 case 0:
550 best_match_dt_entry = cur_dt_entry;
551 found = 1;
552 break;
553 case -1:
554 if (!best_match_dt_entry) {
555 /* copy structure */
David Ng618293a2013-06-25 12:29:03 -0700556 best_match_dt_entry = cur_dt_entry;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800557 cur_dt_entry = &dt_entry_buf_2;
558 } else {
559 /* Swap dt_entry buffers */
560 struct dt_entry *temp = cur_dt_entry;
561 cur_dt_entry = best_match_dt_entry;
562 best_match_dt_entry = temp;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700563 }
Maria Yu2e2d2c22013-07-03 19:20:33 +0800564 default:
565 break;
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800566 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700567 }
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800568
Joel Kingaa335dc2013-06-03 16:11:08 -0700569 if (best_match_dt_entry) {
570 *dt_entry_info = *best_match_dt_entry;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800571 found = 1;
572 }
573
574 if (found != 0) {
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700575 dprintf(INFO, "Using DTB entry 0x%08x/%08x/0x%08x/%u for device 0x%08x/%08x/0x%08x/%u\n",
David Ng618293a2013-06-25 12:29:03 -0700576 dt_entry_info->platform_id, dt_entry_info->soc_rev,
577 dt_entry_info->variant_id, dt_entry_info->board_hw_subtype,
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700578 board_dt_data->platform_variant_id, board_soc_version(),
579 board_dt_data->target_variant_id, board_hardware_subtype());
Joel Kingaa335dc2013-06-03 16:11:08 -0700580 return 0;
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800581 }
582
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700583 dprintf(CRITICAL, "INFO: Unable to find suitable device tree for device (0x%08x/0x%08x/0x%08x/%u)\n",
584 board_dt_data->platform_variant_id, board_soc_version(),
585 board_dt_data->target_variant_id, board_hardware_subtype());
Joel Kingaa335dc2013-06-03 16:11:08 -0700586 return -1;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700587}
588
Maria Yu2e2d2c22013-07-03 19:20:33 +0800589/* Function to obtain the index information for the correct device tree
590 * based on the platform data.
591 * If a matching device tree is found, the information is returned in the
592 * "dt_entry_info" out parameter and a function value of 0 is returned, otherwise
593 * a non-zero function value is returned.
594 */
595int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info)
596{
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700597 struct board_dt_entry board_dt_data;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800598
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700599 /* 1. Look for new board-id (platform version + hw + subtype) & new msm-id (soc ver + soc id + foundry-id) */
600 board_dt_data.target_variant_id = board_target_id();
601 /* Platform-id
602 * bit no |31 24|23 16|15 0|
603 * |reserved|foundry-id|msm-id|
604 */
605 board_dt_data.platform_variant_id = board_platform_id() | (board_foundry_id() << 16);
606 if (__dev_tree_get_entry_info(table, dt_entry_info, &board_dt_data, 0xff) == 0) {
607 return 0;
608 }
609
610 /* 2. Look for new board-id & old msm-id (no foundry-id) */
611 board_dt_data.target_variant_id = board_target_id();
612 board_dt_data.platform_variant_id = board_platform_id();
613 if (__dev_tree_get_entry_info(table, dt_entry_info, &board_dt_data, 0xff) == 0) {
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800614 return 0;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800615 }
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800616
Maria Yu2e2d2c22013-07-03 19:20:33 +0800617 /*
Channagoud Kadabi571193a2014-02-05 13:58:49 -0800618 * for compatible with version 1 and version 2 dtbtool
619 * will compare the subtype inside the variant id
620 */
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700621
622 /* 3. Look for old board-id (no platform version) & new msm-id (with foundry-id) */
623 board_dt_data.target_variant_id = board_hardware_id() | ((board_hardware_subtype() & 0xff) << 24);
624 board_dt_data.platform_variant_id = board_platform_id() | (board_foundry_id() << 16);
625 if (__dev_tree_get_entry_info(table, dt_entry_info, &board_dt_data, 0xff) == 0) {
626 return 0;
627 }
628 /* 4. Look for old board-id (no platform versions) & old msm-id(no foundry-id) */
629 board_dt_data.target_variant_id = board_hardware_id() | ((board_hardware_subtype() & 0xff) << 24);
630 board_dt_data.platform_variant_id = board_platform_id();
631 if (__dev_tree_get_entry_info(table, dt_entry_info, &board_dt_data, 0xff) == 0) {
Maria Yu2e2d2c22013-07-03 19:20:33 +0800632 return 0;
633 }
634
635 /*
636 * add compatible with old device selection method which don't compare subtype
637 */
Sundarajan Srinivasan763c0db2014-05-20 17:08:36 -0700638 board_dt_data.target_variant_id = board_hardware_id();
639 board_dt_data.platform_variant_id = board_platform_id();
640 return __dev_tree_get_entry_info(table, dt_entry_info, &board_dt_data, 0);
Maria Yu2e2d2c22013-07-03 19:20:33 +0800641}
642
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700643/* Function to add the first RAM partition info to the device tree.
644 * Note: The function replaces the reg property in the "/memory" node
645 * with the addr and size provided.
646 */
647int dev_tree_add_first_mem_info(uint32_t *fdt, uint32_t offset, uint32_t addr, uint32_t size)
648{
649 int ret;
650
651 ret = fdt_setprop_u32(fdt, offset, "reg", addr);
652
653 if (ret)
654 {
655 dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
656 ret);
657 }
658
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700659 ret = fdt_appendprop_u32(fdt, offset, "reg", size);
660
661 if (ret)
662 {
663 dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
664 ret);
665 }
666
667 return ret;
668}
669
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700670static int dev_tree_query_memory_cell_sizes(void *fdt, struct dt_mem_node_info *mem_node, uint32_t mem_node_offset)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700671{
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700672 int len;
673 uint32_t *valp;
674 int ret;
675 uint32_t offset;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700676
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700677 mem_node->offset = mem_node_offset;
678
679 /* Get offset of the root node */
680 ret = fdt_path_offset(fdt, "/");
681 if (ret < 0)
682 {
683 dprintf(CRITICAL, "Could not find memory node.\n");
684 return ret;
685 }
686
687 offset = ret;
688
689 /* Find the #address-cells size. */
690 valp = (uint32_t*)fdt_getprop(fdt, offset, "#address-cells", &len);
Lijuan Gaoae0927b2014-07-18 17:16:16 +0800691 if (len <= 0 || !valp)
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700692 {
693 if (len == -FDT_ERR_NOTFOUND)
694 {
695 /* Property not found.
696 * Assume standard sizes.
697 */
698 mem_node->addr_cell_size = 2;
699 dprintf(CRITICAL, "Using default #addr_cell_size: %u\n", mem_node->addr_cell_size);
700 }
701 else
702 {
703 dprintf(CRITICAL, "Error finding the #address-cells property\n");
704 return len;
705 }
706 }
707 else
708 mem_node->addr_cell_size = fdt32_to_cpu(*valp);
709
710 /* Find the #size-cells size. */
711 valp = (uint32_t*)fdt_getprop(fdt, offset, "#size-cells", &len);
Lijuan Gaoae0927b2014-07-18 17:16:16 +0800712 if (len <= 0 || !valp)
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700713 {
714 if (len == -FDT_ERR_NOTFOUND)
715 {
716 /* Property not found.
717 * Assume standard sizes.
718 */
719 mem_node->size_cell_size = 1;
720 dprintf(CRITICAL, "Using default #size_cell_size: %u\n", mem_node->size_cell_size);
721 }
722 else
723 {
724 dprintf(CRITICAL, "Error finding the #size-cells property\n");
725 return len;
726 }
727 }
728 else
729 mem_node->size_cell_size = fdt32_to_cpu(*valp);
730
731 return 0;
732}
733
734static void dev_tree_update_memory_node(uint32_t offset)
735{
736 mem_node.offset = offset;
737 mem_node.addr_cell_size = 1;
738 mem_node.size_cell_size = 1;
739}
740
741/* Function to add the subsequent RAM partition info to the device tree. */
742int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint64_t addr, uint64_t size)
743{
744 int ret = 0;
745
746 if(smem_get_ram_ptable_version() >= 1)
747 {
748 ret = dev_tree_query_memory_cell_sizes(fdt, &mem_node, offset);
749 if (ret < 0)
750 {
751 dprintf(CRITICAL, "Could not find #address-cells and #size-cells properties: ret %d\n", ret);
752 return ret;
753 }
754
755 }
756 else
757 {
758 dev_tree_update_memory_node(offset);
759 }
760
761 if (!(mem_node.mem_info_cnt))
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700762 {
763 /* Replace any other reg prop in the memory node. */
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700764
765 /* cell_size is the number of 32 bit words used to represent an address/length in the device tree.
766 * memory node in DT can be either 32-bit(cell-size = 1) or 64-bit(cell-size = 2).So when updating
767 * the memory node in the device tree, we write one word or two words based on cell_size = 1 or 2.
768 */
769
770 if(mem_node.addr_cell_size == 2)
771 {
772 ret = fdt_setprop_u32(fdt, mem_node.offset, "reg", addr >> 32);
773 if(ret)
774 {
775 dprintf(CRITICAL, "ERROR: Could not set prop reg for memory node\n");
776 return ret;
777 }
778
779 ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
780 if(ret)
781 {
782 dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
783 return ret;
784 }
785 }
786 else
787 {
788 ret = fdt_setprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
789 if(ret)
790 {
791 dprintf(CRITICAL, "ERROR: Could not set prop reg for memory node\n");
792 return ret;
793 }
794 }
795
796 mem_node.mem_info_cnt = 1;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700797 }
798 else
799 {
800 /* Append the mem info to the reg prop for subsequent nodes. */
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700801 if(mem_node.addr_cell_size == 2)
802 {
803 ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", addr >> 32);
804 if(ret)
805 {
806 dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
807 return ret;
808 }
809 }
810
811 ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
812 if(ret)
813 {
814 dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
815 return ret;
816 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700817 }
818
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700819 if(mem_node.size_cell_size == 2)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700820 {
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700821 ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", size>>32);
822 if(ret)
823 {
824 dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
825 return ret;
826 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700827 }
828
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700829 ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700830
831 if (ret)
832 {
833 dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
834 ret);
Sundarajan Srinivasan44de4342013-07-08 14:47:13 -0700835 return ret;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700836 }
837
838 return ret;
839}
840
841/* Top level function that updates the device tree. */
842int update_device_tree(void *fdt, const char *cmdline,
843 void *ramdisk, uint32_t ramdisk_size)
844{
845 int ret = 0;
846 uint32_t offset;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700847
848 /* Check the device tree header */
849 ret = fdt_check_header(fdt);
850 if (ret)
851 {
852 dprintf(CRITICAL, "Invalid device tree header \n");
853 return ret;
854 }
855
Deepa Dinamani1c970732013-04-19 14:23:01 -0700856 /* Add padding to make space for new nodes and properties. */
857 ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + DTB_PAD_SIZE);
858 if (ret!= 0)
859 {
860 dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
861 return ret;
862 }
863
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700864 /* Get offset of the memory node */
865 ret = fdt_path_offset(fdt, "/memory");
866 if (ret < 0)
867 {
868 dprintf(CRITICAL, "Could not find memory node.\n");
869 return ret;
870 }
871
872 offset = ret;
873
874 ret = target_dev_tree_mem(fdt, offset);
875 if(ret)
876 {
877 dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
878 return ret;
879 }
880
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700881 /* Get offset of the chosen node */
882 ret = fdt_path_offset(fdt, "/chosen");
883 if (ret < 0)
884 {
885 dprintf(CRITICAL, "Could not find chosen node.\n");
886 return ret;
887 }
888
889 offset = ret;
890 /* Adding the cmdline to the chosen node */
Aparna Mallavarapu8fdf9312014-07-11 21:03:47 +0530891 ret = fdt_appendprop_string(fdt, offset, (const char*)"bootargs", (const void*)cmdline);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700892 if (ret)
893 {
894 dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
895 return ret;
896 }
897
Joonwoo Parka5b5f492014-02-13 18:24:48 -0800898 if (ramdisk_size) {
899 /* Adding the initrd-start to the chosen node */
900 ret = fdt_setprop_u32(fdt, offset, "linux,initrd-start",
901 (uint32_t)ramdisk);
902 if (ret)
903 {
904 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
905 return ret;
906 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700907
Joonwoo Parka5b5f492014-02-13 18:24:48 -0800908 /* Adding the initrd-end to the chosen node */
909 ret = fdt_setprop_u32(fdt, offset, "linux,initrd-end",
910 ((uint32_t)ramdisk + ramdisk_size));
911 if (ret)
912 {
913 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
914 return ret;
915 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700916 }
917
918 fdt_pack(fdt);
919
920 return ret;
921}
Maria Yuca51ee22013-06-27 21:45:24 +0800922