1 /*
2  * Copyright (c) 2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <common/debug.h>
9 #include <common/desc_image_load.h>
10 #include <drivers/arm/css/sds.h>
11 #include <libfdt.h>
12 #include <plat/common/platform.h>
13 
14 #include "n1sdp_def.h"
15 #include <plat/arm/common/plat_arm.h>
16 
17 /*
18  * Platform information structure stored in SDS.
19  * This structure holds information about platform's DDR
20  * size which will be used to zero out the memory before
21  * enabling the ECC capability as well as information
22  * about multichip setup
23  * 	- multichip mode
24  * 	- secondary_count
25  * 	- Local DDR size in GB, DDR memory in master board
26  * 	- Remote DDR size in GB, DDR memory in secondary board
27  */
28 struct n1sdp_plat_info {
29 	bool multichip_mode;
30 	uint8_t secondary_count;
31 	uint8_t local_ddr_size;
32 	uint8_t remote_ddr_size;
33 } __packed;
34 
35 /*******************************************************************************
36  * This function inserts Platform information via device tree nodes as,
37  *	platform-info {
38  *		multichip-mode = <0x0>;
39  *		secondary-chip-count = <0x0>;
40  *		local-ddr-size = <0x0>;
41  *		remote-ddr-size = <0x0>;
42  *	};
43  ******************************************************************************/
plat_n1sdp_append_config_node(struct n1sdp_plat_info * plat_info)44 static int plat_n1sdp_append_config_node(struct n1sdp_plat_info *plat_info)
45 {
46 	bl_mem_params_node_t *mem_params;
47 	void *fdt;
48 	int nodeoffset, err;
49 
50 	mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
51 	if (mem_params == NULL) {
52 		ERROR("NT_FW CONFIG base address is NULL\n");
53 		return -1;
54 	}
55 
56 	fdt = (void *)(mem_params->image_info.image_base);
57 
58 	/* Check the validity of the fdt */
59 	if (fdt_check_header(fdt) != 0) {
60 		ERROR("Invalid NT_FW_CONFIG DTB passed\n");
61 		return -1;
62 	}
63 
64 	nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info");
65 	if (nodeoffset < 0) {
66 		ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
67 		return -1;
68 	}
69 
70 	err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode",
71 			plat_info->multichip_mode);
72 	if (err < 0) {
73 		ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
74 		return -1;
75 	}
76 
77 	err = fdt_setprop_u32(fdt, nodeoffset, "secondary-chip-count",
78 			plat_info->secondary_count);
79 	if (err < 0) {
80 		ERROR("NT_FW_CONFIG: Failed to set secondary-chip-count\n");
81 		return -1;
82 	}
83 
84 	err = fdt_setprop_u32(fdt, nodeoffset, "local-ddr-size",
85 			plat_info->local_ddr_size);
86 	if (err < 0) {
87 		ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
88 		return -1;
89 	}
90 
91 	err = fdt_setprop_u32(fdt, nodeoffset, "remote-ddr-size",
92 			plat_info->remote_ddr_size);
93 	if (err < 0) {
94 		ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
95 		return -1;
96 	}
97 
98 	flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
99 
100 	return 0;
101 }
102 
103 /*******************************************************************************
104  * This function returns the list of executable images.
105  ******************************************************************************/
plat_get_next_bl_params(void)106 bl_params_t *plat_get_next_bl_params(void)
107 {
108 	int ret;
109 	struct n1sdp_plat_info plat_info;
110 
111 	ret = sds_init();
112 	if (ret != SDS_OK) {
113 		ERROR("SDS initialization failed. ret:%d\n", ret);
114 		panic();
115 	}
116 
117 	ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
118 				N1SDP_SDS_PLATFORM_INFO_OFFSET,
119 				&plat_info,
120 				N1SDP_SDS_PLATFORM_INFO_SIZE,
121 				SDS_ACCESS_MODE_NON_CACHED);
122 	if (ret != SDS_OK) {
123 		ERROR("Error getting platform info from SDS. ret:%d\n", ret);
124 		panic();
125 	}
126 
127 	/* Validate plat_info SDS */
128 	if ((plat_info.local_ddr_size == 0U)
129 		|| (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
130 		|| (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
131 		|| (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)
132 		){
133 		ERROR("platform info SDS is corrupted\n");
134 		panic();
135 	}
136 
137 	ret = plat_n1sdp_append_config_node(&plat_info);
138 	if (ret != 0) {
139 		panic();
140 	}
141 
142 	return arm_get_next_bl_params();
143 }
144