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