1 /*
2 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <assert.h>
7
8 #include <common/debug.h>
9 #include <common/fdt_wrappers.h>
10 #include <libfdt.h>
11 #include <plat/arm/common/fconf_sec_intr_config.h>
12
13 #define G0_INTR_NUM(i) g0_intr_prop[3U * (i)]
14 #define G0_INTR_PRIORITY(i) g0_intr_prop[3U * (i) + 1]
15 #define G0_INTR_CONFIG(i) g0_intr_prop[3U * (i) + 2]
16
17 #define G1S_INTR_NUM(i) g1s_intr_prop[3U * (i)]
18 #define G1S_INTR_PRIORITY(i) g1s_intr_prop[3U * (i) + 1]
19 #define G1S_INTR_CONFIG(i) g1s_intr_prop[3U * (i) + 2]
20
21 struct sec_intr_prop_t sec_intr_prop;
22
print_intr_prop(interrupt_prop_t prop)23 static void print_intr_prop(interrupt_prop_t prop)
24 {
25 VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n",
26 prop.intr_num, prop.intr_pri, prop.intr_cfg);
27 }
28
fconf_populate_sec_intr_config(uintptr_t config)29 int fconf_populate_sec_intr_config(uintptr_t config)
30 {
31 int node, err;
32 uint32_t g0_intr_count, g1s_intr_count;
33 uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3];
34 uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3];
35
36 /* Necessary to work with libfdt APIs */
37 const void *hw_config_dtb = (const void *)config;
38
39 node = fdt_node_offset_by_compatible(hw_config_dtb, -1,
40 "arm,secure_interrupt_desc");
41 if (node < 0) {
42 ERROR("FCONF: Unable to locate node with %s compatible property\n",
43 "arm,secure_interrupt_desc");
44 return node;
45 }
46
47 /* Read number of Group 0 interrupts specified by platform */
48 err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count);
49 if (err < 0) {
50 ERROR("FCONF: Could not locate g0s_intr_cnt property\n");
51 return err;
52 }
53
54 /* At least 1 Group 0 interrupt description has to be provided*/
55 if (g0_intr_count < 1U) {
56 ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n");
57 return -1;
58 }
59
60 /* Read number of Group 1 secure interrupts specified by platform */
61 err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt",
62 &g1s_intr_count);
63 if (err < 0) {
64 ERROR("FCONF: Could not locate g1s_intr_cnt property\n");
65 return err;
66 }
67
68 /* At least one Group 1 interrupt description has to be provided*/
69 if (g1s_intr_count < 1U) {
70 ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n");
71 return -1;
72 }
73
74 /*
75 * Check if the total number of secure interrupts described are within
76 * the limit defined statically by the platform.
77 */
78 if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) {
79 ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n",
80 SEC_INT_COUNT_MAX);
81 return -1;
82 }
83
84 sec_intr_prop.count = g0_intr_count + g1s_intr_count;
85
86 /* Read the Group 0 interrupt descriptors */
87 err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc",
88 g0_intr_count * 3, g0_intr_prop);
89 if (err < 0) {
90 ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err);
91 return err;
92 }
93
94 /* Read the Group 1 secure interrupt descriptors */
95 err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc",
96 g1s_intr_count * 3, g1s_intr_prop);
97 if (err < 0) {
98 ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err);
99 return err;
100 }
101
102 /* Populate Group 0 interrupt descriptors into fconf based C struct */
103 for (uint32_t i = 0; i < g0_intr_count; i++) {
104 interrupt_prop_t sec_intr_property;
105
106 /* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */
107 sec_intr_property.intr_grp = 1;
108 sec_intr_property.intr_num = G0_INTR_NUM(i);
109 sec_intr_property.intr_pri = G0_INTR_PRIORITY(i);
110 sec_intr_property.intr_cfg = G0_INTR_CONFIG(i);
111 sec_intr_prop.descriptor[i] = sec_intr_property;
112 print_intr_prop(sec_intr_property);
113 }
114
115 /* Populate G1 secure interrupt descriptors into fconf based C struct */
116 for (uint32_t i = 0; i < g1s_intr_count; i++) {
117 interrupt_prop_t sec_intr_property;
118
119 /* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */
120 sec_intr_property.intr_grp = 0;
121 sec_intr_property.intr_num = G1S_INTR_NUM(i);
122 sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i);
123 sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i);
124 sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property;
125 print_intr_prop(sec_intr_property);
126 }
127
128 return 0;
129 }
130
131 FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config);
132