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