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 <assert.h>
8 #include <string.h>
9 
10 #include <bl31/interrupt_mgmt.h>
11 #include <plat/common/platform.h>
12 #include <platform_def.h>
13 
14 #include <nrd_ras.h>
15 
16 static struct plat_nrd_ras_config *nrd_ras_config;
17 
18 /*
19  * Find event map for a given interrupt number. On success, returns pointer to
20  * the event map. On error, returns NULL.
21  */
nrd_find_ras_event_map_by_intr(uint32_t intr_num)22 struct nrd_ras_ev_map *nrd_find_ras_event_map_by_intr(uint32_t intr_num)
23 {
24 	struct nrd_ras_ev_map *map;
25 	int size;
26 	int i;
27 
28 	if (nrd_ras_config == NULL) {
29 		ERROR("RAS config is NULL\n");
30 		return NULL;
31 	}
32 
33 	map = nrd_ras_config->ev_map;
34 	size = nrd_ras_config->ev_map_size;
35 
36 	for (i = 0; i < size; i++) {
37 		if (map->intr == intr_num)
38 			return map;
39 
40 		map++;
41 	}
42 
43 	return NULL;
44 }
45 
46 /*
47  * Programs GIC registers and configures interrupt ID's as Group0 EL3
48  * interrupts. Current support is to register PPI and SPI interrupts.
49  */
nrd_ras_intr_configure(int intr,int intr_type)50 static void nrd_ras_intr_configure(int intr, int intr_type)
51 {
52 	plat_ic_set_interrupt_type(intr, INTR_TYPE_EL3);
53 	plat_ic_set_interrupt_priority(intr, PLAT_RAS_PRI);
54 	plat_ic_clear_interrupt_pending(intr);
55 
56 	/* Routing mode option available only for SPI interrupts */
57 	if (intr_type == NRD_RAS_INTR_TYPE_SPI) {
58 		plat_ic_set_spi_routing(intr, INTR_ROUTING_MODE_ANY,
59 					(u_register_t)read_mpidr_el1());
60 	}
61 	plat_ic_enable_interrupt(intr);
62 }
63 
64 /*
65  * Initialization function for the framework.
66  *
67  * Registers RAS config provided by the platform and then configures and
68  * enables interrupt for each registered error. On success, return 0.
69  */
nrd_ras_platform_setup(struct plat_nrd_ras_config * config)70 int nrd_ras_platform_setup(struct plat_nrd_ras_config *config)
71 {
72 	struct nrd_ras_ev_map *map;
73 	int size;
74 	int i;
75 
76 	/* Check if parameter is valid. */
77 	if (config == NULL) {
78 		ERROR("NRD: Failed to register RAS config\n");
79 		return -1;
80 	}
81 
82 	/*
83 	 * Maintain a reference to the platform RAS config data for later
84 	 * use.
85 	 */
86 	nrd_ras_config = config;
87 
88 	map = nrd_ras_config->ev_map;
89 	size = nrd_ras_config->ev_map_size;
90 
91 	for (i = 0; i < size; i++) {
92 		nrd_ras_intr_configure(map->intr, map->intr_type);
93 		map++;
94 	}
95 
96 	INFO("NRD: Platform RAS setup successful\n");
97 
98 	return 0;
99 }
100