blob: 85d927de264dead8b2d5dc679d87de36c9709e86 [file] [log] [blame]
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +05301/*
Rohit Mathewa0dd3072024-02-03 17:22:54 +00002 * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +05303 *
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
Rohit Mathewa0dd3072024-02-03 17:22:54 +000014#include <nrd_ras.h>
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053015
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000016static struct plat_nrd_ras_config *nrd_ras_config;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053017
18/*
19 * Find event map for a given interrupt number. On success, returns pointer to
20 * the event map. On error, returns NULL.
21 */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000022struct nrd_ras_ev_map *nrd_find_ras_event_map_by_intr(uint32_t intr_num)
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053023{
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000024 struct nrd_ras_ev_map *map;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053025 int size;
26 int i;
27
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000028 if (nrd_ras_config == NULL) {
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053029 ERROR("RAS config is NULL\n");
30 return NULL;
31 }
32
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000033 map = nrd_ras_config->ev_map;
34 size = nrd_ras_config->ev_map_size;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053035
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 */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000050static void nrd_ras_intr_configure(int intr, int intr_type)
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053051{
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 == SGI_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 */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000070int nrd_ras_platform_setup(struct plat_nrd_ras_config *config)
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053071{
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000072 struct nrd_ras_ev_map *map;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053073 int size;
74 int i;
75
76 /* Check if parameter is valid. */
77 if (config == NULL) {
78 ERROR("SGI: 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 */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000086 nrd_ras_config = config;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053087
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000088 map = nrd_ras_config->ev_map;
89 size = nrd_ras_config->ev_map_size;
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053090
91 for (i = 0; i < size; i++) {
Rohit Mathew0ec6ed92024-02-03 18:39:10 +000092 nrd_ras_intr_configure(map->intr, map->intr_type);
Omkar Anand Kulkarniaa8abf02023-05-31 11:29:17 +053093 map++;
94 }
95
96 INFO("SGI: Platform RAS setup successful\n");
97
98 return 0;
99}