1 /*
2  * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <common/debug.h>
10 #include <common/interrupt_props.h>
11 #include <drivers/arm/gicv3.h>
12 #include "gicv3_private.h"
13 
14 /*******************************************************************************
15  * GIC Redistributor functions
16  * Note: The raw register values correspond to multiple interrupt `id`s and
17  * the number of interrupt `id`s involved depends on the register accessed.
18  ******************************************************************************/
19 
20 /*
21  * Accessors to read/write the GIC Redistributor IPRIORITYR and IPRIORITYRE
22  * register corresponding to the interrupt `id`, 4 interrupts IDs at a time.
23  */
gicr_read_ipriorityr(uintptr_t base,unsigned int id)24 unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
25 {
26 	return GICR_READ(IPRIORITY, base, id);
27 }
28 
gicr_write_ipriorityr(uintptr_t base,unsigned int id,unsigned int val)29 void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
30 {
31 	GICR_WRITE(IPRIORITY, base, id, val);
32 }
33 
34 /*
35  * Accessor to set the byte corresponding to interrupt `id`
36  * in GIC Redistributor IPRIORITYR and IPRIORITYRE.
37  */
gicr_set_ipriorityr(uintptr_t base,unsigned int id,unsigned int pri)38 void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
39 {
40 	GICR_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK));
41 }
42 
43 /*
44  * Accessors to get/set/clear the bit corresponding to interrupt `id`
45  * from GIC Redistributor IGROUPR0 and IGROUPRE
46  */
gicr_get_igroupr(uintptr_t base,unsigned int id)47 unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id)
48 {
49 	return GICR_GET_BIT(IGROUP, base, id);
50 }
51 
gicr_set_igroupr(uintptr_t base,unsigned int id)52 void gicr_set_igroupr(uintptr_t base, unsigned int id)
53 {
54 	GICR_SET_BIT(IGROUP, base, id);
55 }
56 
gicr_clr_igroupr(uintptr_t base,unsigned int id)57 void gicr_clr_igroupr(uintptr_t base, unsigned int id)
58 {
59 	GICR_CLR_BIT(IGROUP, base, id);
60 }
61 
62 /*
63  * Accessors to get/set/clear the bit corresponding to interrupt `id`
64  * from GIC Redistributor IGRPMODR0 and IGRPMODRE
65  */
gicr_get_igrpmodr(uintptr_t base,unsigned int id)66 unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id)
67 {
68 	return GICR_GET_BIT(IGRPMOD, base, id);
69 }
70 
gicr_set_igrpmodr(uintptr_t base,unsigned int id)71 void gicr_set_igrpmodr(uintptr_t base, unsigned int id)
72 {
73 	GICR_SET_BIT(IGRPMOD, base, id);
74 }
75 
gicr_clr_igrpmodr(uintptr_t base,unsigned int id)76 void gicr_clr_igrpmodr(uintptr_t base, unsigned int id)
77 {
78 	GICR_CLR_BIT(IGRPMOD, base, id);
79 }
80 
81 /*
82  * Accessor to write the bit corresponding to interrupt `id`
83  * in GIC Redistributor ISENABLER0 and ISENABLERE
84  */
gicr_set_isenabler(uintptr_t base,unsigned int id)85 void gicr_set_isenabler(uintptr_t base, unsigned int id)
86 {
87 	GICR_WRITE_BIT(ISENABLE, base, id);
88 }
89 
90 /*
91  * Accessor to write the bit corresponding to interrupt `id`
92  * in GIC Redistributor ICENABLER0 and ICENABLERE
93  */
gicr_set_icenabler(uintptr_t base,unsigned int id)94 void gicr_set_icenabler(uintptr_t base, unsigned int id)
95 {
96 	GICR_WRITE_BIT(ICENABLE, base, id);
97 }
98 
99 /*
100  * Accessor to get the bit corresponding to interrupt `id`
101  * in GIC Redistributor ISACTIVER0 and ISACTIVERE
102  */
gicr_get_isactiver(uintptr_t base,unsigned int id)103 unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id)
104 {
105 	return	GICR_GET_BIT(ISACTIVE, base, id);
106 }
107 
108 /*
109  * Accessor to clear the bit corresponding to interrupt `id`
110  * in GIC Redistributor ICPENDR0 and ICPENDRE
111  */
gicr_set_icpendr(uintptr_t base,unsigned int id)112 void gicr_set_icpendr(uintptr_t base, unsigned int id)
113 {
114 	GICR_WRITE_BIT(ICPEND, base, id);
115 }
116 
117 /*
118  * Accessor to write the bit corresponding to interrupt `id`
119  * in GIC Redistributor ISPENDR0 and ISPENDRE
120  */
gicr_set_ispendr(uintptr_t base,unsigned int id)121 void gicr_set_ispendr(uintptr_t base, unsigned int id)
122 {
123 	GICR_WRITE_BIT(ISPEND, base, id);
124 }
125 
126 /*
127  * Accessor to set the bit fields corresponding to interrupt `id`
128  * in GIC Redistributor ICFGR0, ICFGR1 and ICFGRE
129  */
gicr_set_icfgr(uintptr_t base,unsigned int id,unsigned int cfg)130 void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
131 {
132 	/* Interrupt configuration is a 2-bit field */
133 	unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U;
134 
135 	/* Clear the field, and insert required configuration */
136 	mmio_clrsetbits_32(base + GICR_OFFSET(ICFG, id),
137 				(uint32_t)GIC_CFG_MASK << bit_shift,
138 				(cfg & GIC_CFG_MASK) << bit_shift);
139 }
140