xref: /rk3399_ARM-atf/plat/common/plat_gicv2.c (revision 979225f4eed00d631bb57ebd09068edd91b8df7b)
1 /*
2  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <assert.h>
7 #include <gic_common.h>
8 #include <gicv2.h>
9 #include <interrupt_mgmt.h>
10 
11 /*
12  * The following platform GIC functions are weakly defined. They
13  * provide typical implementations that may be re-used by multiple
14  * platforms but may also be overridden by a platform if required.
15  */
16 #pragma weak plat_ic_get_pending_interrupt_id
17 #pragma weak plat_ic_get_pending_interrupt_type
18 #pragma weak plat_ic_acknowledge_interrupt
19 #pragma weak plat_ic_get_interrupt_type
20 #pragma weak plat_ic_end_of_interrupt
21 #pragma weak plat_interrupt_type_to_line
22 
23 #pragma weak plat_ic_get_running_priority
24 #pragma weak plat_ic_is_spi
25 #pragma weak plat_ic_is_ppi
26 #pragma weak plat_ic_is_sgi
27 #pragma weak plat_ic_get_interrupt_active
28 #pragma weak plat_ic_enable_interrupt
29 #pragma weak plat_ic_disable_interrupt
30 
31 /*
32  * This function returns the highest priority pending interrupt at
33  * the Interrupt controller
34  */
35 uint32_t plat_ic_get_pending_interrupt_id(void)
36 {
37 	unsigned int id;
38 
39 	id = gicv2_get_pending_interrupt_id();
40 	if (id == GIC_SPURIOUS_INTERRUPT)
41 		return INTR_ID_UNAVAILABLE;
42 
43 	return id;
44 }
45 
46 /*
47  * This function returns the type of the highest priority pending interrupt
48  * at the Interrupt controller. In the case of GICv2, the Highest Priority
49  * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of
50  * the pending interrupt. The type of interrupt depends upon the id value
51  * as follows.
52  *   1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt
53  *   2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt.
54  *   3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
55  *           type.
56  */
57 uint32_t plat_ic_get_pending_interrupt_type(void)
58 {
59 	unsigned int id;
60 
61 	id = gicv2_get_pending_interrupt_type();
62 
63 	/* Assume that all secure interrupts are S-EL1 interrupts */
64 	if (id < PENDING_G1_INTID)
65 		return INTR_TYPE_S_EL1;
66 
67 	if (id == GIC_SPURIOUS_INTERRUPT)
68 		return INTR_TYPE_INVAL;
69 
70 	return INTR_TYPE_NS;
71 }
72 
73 /*
74  * This function returns the highest priority pending interrupt at
75  * the Interrupt controller and indicates to the Interrupt controller
76  * that the interrupt processing has started.
77  */
78 uint32_t plat_ic_acknowledge_interrupt(void)
79 {
80 	return gicv2_acknowledge_interrupt();
81 }
82 
83 /*
84  * This function returns the type of the interrupt `id`, depending on how
85  * the interrupt has been configured in the interrupt controller
86  */
87 uint32_t plat_ic_get_interrupt_type(uint32_t id)
88 {
89 	unsigned int type;
90 
91 	type = gicv2_get_interrupt_group(id);
92 
93 	/* Assume that all secure interrupts are S-EL1 interrupts */
94 	return (type) ? INTR_TYPE_NS : INTR_TYPE_S_EL1;
95 }
96 
97 /*
98  * This functions is used to indicate to the interrupt controller that
99  * the processing of the interrupt corresponding to the `id` has
100  * finished.
101  */
102 void plat_ic_end_of_interrupt(uint32_t id)
103 {
104 	gicv2_end_of_interrupt(id);
105 }
106 
107 /*
108  * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
109  * The interrupt controller knows which pin/line it uses to signal a type of
110  * interrupt. It lets the interrupt management framework determine
111  * for a type of interrupt and security state, which line should be used in the
112  * SCR_EL3 to control its routing to EL3. The interrupt line is represented
113  * as the bit position of the IRQ or FIQ bit in the SCR_EL3.
114  */
115 uint32_t plat_interrupt_type_to_line(uint32_t type,
116 				uint32_t security_state)
117 {
118 	assert(type == INTR_TYPE_S_EL1 ||
119 		       type == INTR_TYPE_EL3 ||
120 		       type == INTR_TYPE_NS);
121 
122 	/* Non-secure interrupts are signaled on the IRQ line always */
123 	if (type == INTR_TYPE_NS)
124 		return __builtin_ctz(SCR_IRQ_BIT);
125 
126 	/*
127 	 * Secure interrupts are signaled using the IRQ line if the FIQ is
128 	 * not enabled else they are signaled using the FIQ line.
129 	 */
130 	return ((gicv2_is_fiq_enabled()) ? __builtin_ctz(SCR_FIQ_BIT) :
131 						__builtin_ctz(SCR_IRQ_BIT));
132 }
133 
134 unsigned int plat_ic_get_running_priority(void)
135 {
136 	return gicv2_get_running_priority();
137 }
138 
139 int plat_ic_is_spi(unsigned int id)
140 {
141 	return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID);
142 }
143 
144 int plat_ic_is_ppi(unsigned int id)
145 {
146 	return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID);
147 }
148 
149 int plat_ic_is_sgi(unsigned int id)
150 {
151 	return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID);
152 }
153 
154 unsigned int plat_ic_get_interrupt_active(unsigned int id)
155 {
156 	return gicv2_get_interrupt_active(id);
157 }
158 
159 void plat_ic_enable_interrupt(unsigned int id)
160 {
161 	gicv2_enable_interrupt(id);
162 }
163 
164 void plat_ic_disable_interrupt(unsigned int id)
165 {
166 	gicv2_disable_interrupt(id);
167 }
168