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 IDs and 17 * the number of interrupt IDs involved depends on the register accessed. 18 ******************************************************************************/ 19 20 /* 21 * Accessor to read the GIC Redistributor IPRIORITYR corresponding to the 22 * interrupt `id`, 4 interrupts IDs at a time. 23 */ 24 unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id) 25 { 26 unsigned int n = id >> IPRIORITYR_SHIFT; 27 28 return mmio_read_32(base + GICR_IPRIORITYR + (n << 2)); 29 } 30 31 /* 32 * Accessor to write the GIC Redistributor IPRIORITYR corresponding to the 33 * interrupt `id`, 4 interrupts IDs at a time. 34 */ 35 void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) 36 { 37 unsigned int n = id >> IPRIORITYR_SHIFT; 38 39 mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val); 40 } 41 42 /* 43 * Accessor to set the byte corresponding to interrupt ID 44 * in GIC Redistributor IPRIORITYR. 45 */ 46 void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) 47 { 48 GICR_WRITE_8(IPRIORITYR, base, id, pri & GIC_PRI_MASK); 49 } 50 51 /* 52 * Accessor to get the bit corresponding to interrupt ID 53 * from GIC Redistributor IGROUPR0. 54 */ 55 unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id) 56 { 57 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 58 unsigned int reg_val = gicr_read_igroupr0(base); 59 60 return (reg_val >> bit_num) & 0x1U; 61 } 62 63 /* 64 * Accessor to set the bit corresponding to interrupt ID 65 * in GIC Redistributor IGROUPR0. 66 */ 67 void gicr_set_igroupr0(uintptr_t base, unsigned int id) 68 { 69 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 70 unsigned int reg_val = gicr_read_igroupr0(base); 71 72 gicr_write_igroupr0(base, reg_val | (1U << bit_num)); 73 } 74 75 /* 76 * Accessor to clear the bit corresponding to interrupt ID 77 * in GIC Redistributor IGROUPR0. 78 */ 79 void gicr_clr_igroupr0(uintptr_t base, unsigned int id) 80 { 81 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 82 unsigned int reg_val = gicr_read_igroupr0(base); 83 84 gicr_write_igroupr0(base, reg_val & ~(1U << bit_num)); 85 } 86 87 /* 88 * Accessor to get the bit corresponding to interrupt ID 89 * from GIC Redistributor IGRPMODR0. 90 */ 91 unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id) 92 { 93 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); 94 unsigned int reg_val = gicr_read_igrpmodr0(base); 95 96 return (reg_val >> bit_num) & 0x1U; 97 } 98 99 /* 100 * Accessor to set the bit corresponding to interrupt ID 101 * in GIC Redistributor IGRPMODR0. 102 */ 103 void gicr_set_igrpmodr0(uintptr_t base, unsigned int id) 104 { 105 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); 106 unsigned int reg_val = gicr_read_igrpmodr0(base); 107 108 gicr_write_igrpmodr0(base, reg_val | (1U << bit_num)); 109 } 110 111 /* 112 * Accessor to clear the bit corresponding to interrupt ID 113 * in GIC Redistributor IGRPMODR0. 114 */ 115 void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id) 116 { 117 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); 118 unsigned int reg_val = gicr_read_igrpmodr0(base); 119 120 gicr_write_igrpmodr0(base, reg_val & ~(1U << bit_num)); 121 } 122 123 /* 124 * Accessor to set the bit corresponding to interrupt ID 125 * in GIC Redistributor ISENABLER0. 126 */ 127 void gicr_set_isenabler0(uintptr_t base, unsigned int id) 128 { 129 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); 130 131 gicr_write_isenabler0(base, (1U << bit_num)); 132 } 133 134 /* 135 * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor 136 * ICENABLER0. 137 */ 138 void gicr_set_icenabler0(uintptr_t base, unsigned int id) 139 { 140 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); 141 142 gicr_write_icenabler0(base, (1U << bit_num)); 143 } 144 145 /* 146 * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor 147 * ISACTIVER0. 148 */ 149 unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id) 150 { 151 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); 152 unsigned int reg_val = gicr_read_isactiver0(base); 153 154 return (reg_val >> bit_num) & 0x1U; 155 } 156 157 /* 158 * Accessor to clear the bit corresponding to interrupt ID in GIC Redistributor 159 * ICPENDRR0. 160 */ 161 void gicr_set_icpendr0(uintptr_t base, unsigned int id) 162 { 163 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); 164 165 gicr_write_icpendr0(base, (1U << bit_num)); 166 } 167 168 /* 169 * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor 170 * ISPENDR0. 171 */ 172 void gicr_set_ispendr0(uintptr_t base, unsigned int id) 173 { 174 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); 175 176 gicr_write_ispendr0(base, (1U << bit_num)); 177 } 178 179 /* 180 * Accessor to set the bit fields corresponding to interrupt ID 181 * in GIC Redistributor ICFGR0. 182 */ 183 void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg) 184 { 185 /* Interrupt configuration is a 2-bit field */ 186 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); 187 unsigned int bit_shift = bit_num << 1U; 188 189 uint32_t reg_val = gicr_read_icfgr0(base); 190 191 /* Clear the field, and insert required configuration */ 192 reg_val &= ~(GIC_CFG_MASK << bit_shift); 193 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); 194 195 gicr_write_icfgr0(base, reg_val); 196 } 197 198 /* 199 * Accessor to set the bit fields corresponding to interrupt ID 200 * in GIC Redistributor ICFGR1. 201 */ 202 void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg) 203 { 204 /* Interrupt configuration is a 2-bit field */ 205 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); 206 unsigned int bit_shift = bit_num << 1U; 207 208 uint32_t reg_val = gicr_read_icfgr1(base); 209 210 /* Clear the field, and insert required configuration */ 211 reg_val &= ~(GIC_CFG_MASK << bit_shift); 212 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); 213 214 gicr_write_icfgr1(base, reg_val); 215 } 216