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 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 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