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