1 /*
2 * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <libfdt.h>
8
9 #include <arch_helpers.h>
10 #include <common/debug.h>
11 #include <common/desc_image_load.h>
12 #include <drivers/arm/css/sds.h>
13 #include <plat/arm/common/plat_arm.h>
14 #include <plat/common/platform.h>
15 #include <platform_def.h>
16
17 #include <nrd_variant.h>
18
19 /*
20 * Information about the isolated CPUs obtained from SDS.
21 */
22 struct isolated_cpu_mpid_list {
23 uint64_t num_entries; /* Number of entries in the list */
24 uint64_t mpid_list[PLATFORM_CORE_COUNT]; /* List of isolated CPU MPIDs */
25 };
26
27 /* Function to read isolated CPU MPID list from SDS. */
plat_arm_nrd_get_isolated_cpu_list(struct isolated_cpu_mpid_list * list)28 void plat_arm_nrd_get_isolated_cpu_list(struct isolated_cpu_mpid_list *list)
29 {
30 int ret;
31
32 ret = sds_init(SDS_SCP_AP_REGION_ID);
33 if (ret != SDS_OK) {
34 ERROR("SDS initialization failed, error: %d\n", ret);
35 panic();
36 }
37
38 ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
39 SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries,
40 sizeof(list->num_entries), SDS_ACCESS_MODE_CACHED);
41 if (ret != SDS_OK) {
42 INFO("SDS CPU num elements read failed, error: %d\n", ret);
43 list->num_entries = 0;
44 return;
45 }
46
47 if (list->num_entries > PLATFORM_CORE_COUNT) {
48 ERROR("Isolated CPU list count %ld greater than max"
49 " number supported %d\n",
50 list->num_entries, PLATFORM_CORE_COUNT);
51 panic();
52 } else if (list->num_entries == 0) {
53 INFO("SDS isolated CPU list is empty\n");
54 return;
55 }
56
57 ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
58 SDS_ISOLATED_CPU_LIST_ID,
59 sizeof(list->num_entries),
60 &list->mpid_list,
61 sizeof(list->mpid_list[0]) * list->num_entries,
62 SDS_ACCESS_MODE_CACHED);
63 if (ret != SDS_OK) {
64 ERROR("SDS CPU list read failed. error: %d\n", ret);
65 panic();
66 }
67 }
68
69 /*******************************************************************************
70 * This function inserts Platform information via device tree nodes as,
71 * system-id {
72 * platform-id = <0>;
73 * config-id = <0>;
74 * isolated-cpu-list = <0>
75 * }
76 ******************************************************************************/
plat_nrd_append_config_node(void)77 static int plat_nrd_append_config_node(void)
78 {
79 bl_mem_params_node_t *mem_params;
80 void *fdt;
81 int nodeoffset, err;
82 unsigned int platid = 0, platcfg = 0;
83 struct isolated_cpu_mpid_list cpu_mpid_list = {0};
84
85 mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
86 if (mem_params == NULL) {
87 ERROR("NT_FW CONFIG base address is NULL");
88 return -1;
89 }
90
91 fdt = (void *)(mem_params->image_info.image_base);
92
93 /* Check the validity of the fdt */
94 if (fdt_check_header(fdt) != 0) {
95 ERROR("Invalid NT_FW_CONFIG DTB passed\n");
96 return -1;
97 }
98
99 nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
100 if (nodeoffset < 0) {
101 ERROR("Failed to get system-id node offset\n");
102 return -1;
103 }
104
105 platid = plat_arm_nrd_get_platform_id();
106 err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
107 if (err < 0) {
108 ERROR("Failed to set platform-id\n");
109 return -1;
110 }
111
112 platcfg = plat_arm_nrd_get_config_id();
113 err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
114 if (err < 0) {
115 ERROR("Failed to set config-id\n");
116 return -1;
117 }
118
119 platcfg = plat_arm_nrd_get_multi_chip_mode();
120 err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg);
121 if (err < 0) {
122 ERROR("Failed to set multi-chip-mode\n");
123 return -1;
124 }
125
126 plat_arm_nrd_get_isolated_cpu_list(&cpu_mpid_list);
127 if (cpu_mpid_list.num_entries > 0) {
128 err = fdt_setprop(fdt, nodeoffset, "isolated-cpu-list",
129 &cpu_mpid_list,
130 (sizeof(cpu_mpid_list.num_entries) *
131 (cpu_mpid_list.num_entries + 1)));
132 if (err < 0) {
133 ERROR("Failed to set isolated-cpu-list, error: %d\n",
134 err);
135 }
136 }
137
138 flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
139
140 return 0;
141 }
142
143 /*******************************************************************************
144 * This function returns the list of executable images.
145 ******************************************************************************/
plat_get_next_bl_params(void)146 bl_params_t *plat_get_next_bl_params(void)
147 {
148 int ret;
149
150 ret = plat_nrd_append_config_node();
151 if (ret != 0)
152 panic();
153
154 return arm_get_next_bl_params();
155 }
156