Sandrine Bailleux | 3cd87d7 | 2018-10-09 11:12:55 +0200 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2018, Arm Limited. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #ifndef __GIC_V2_H__ |
| 8 | #define __GIC_V2_H__ |
| 9 | |
| 10 | /*************************************************************************** |
| 11 | * Defines and prototypes specific to GIC v2. |
| 12 | **************************************************************************/ |
| 13 | |
| 14 | /* GICD_CTLR bit definitions */ |
| 15 | #define GICD_CTLR_ENABLE (1 << 0) |
| 16 | |
| 17 | /* Distributor interface register offsets */ |
| 18 | #define GICD_ITARGETSR 0x800 |
| 19 | #define GICD_SGIR 0xF00 |
| 20 | #define GICD_CPENDSGIR 0xF10 |
| 21 | #define GICD_SPENDSGIR 0xF20 |
| 22 | |
| 23 | /* GIC Distributor register shifts */ |
| 24 | #define ITARGETSR_SHIFT 2 |
| 25 | #define CPENDSGIR_SHIFT 2 |
| 26 | #define SPENDSGIR_SHIFT CPENDSGIR_SHIFT |
| 27 | |
| 28 | /* GICD_SGIR bit shifts */ |
| 29 | #define GICD_SGIR_INTID_SHIFT 0 |
| 30 | #define GICD_SGIR_CPUTL_SHIFT 16 |
| 31 | |
| 32 | /* Physical CPU Interface register offsets */ |
| 33 | #define GICC_CTLR 0x0 |
| 34 | #define GICC_PMR 0x4 |
| 35 | #define GICC_BPR 0x8 |
| 36 | #define GICC_IAR 0xC |
| 37 | #define GICC_EOIR 0x10 |
| 38 | #define GICC_RPR 0x14 |
| 39 | #define GICC_HPPIR 0x18 |
| 40 | #define GICC_AHPPIR 0x28 |
| 41 | #define GICC_IIDR 0xFC |
| 42 | #define GICC_DIR 0x1000 |
| 43 | #define GICC_PRIODROP GICC_EOIR |
| 44 | |
| 45 | /* GICC_IIDR bit masks and shifts */ |
| 46 | #define GICC_IIDR_PID_SHIFT 20 |
| 47 | #define GICC_IIDR_ARCH_SHIFT 16 |
| 48 | #define GICC_IIDR_REV_SHIFT 12 |
| 49 | #define GICC_IIDR_IMP_SHIFT 0 |
| 50 | |
| 51 | #define GICC_IIDR_PID_MASK 0xfff |
| 52 | #define GICC_IIDR_ARCH_MASK 0xf |
| 53 | #define GICC_IIDR_REV_MASK 0xf |
| 54 | #define GICC_IIDR_IMP_MASK 0xfff |
| 55 | |
| 56 | /* HYP view virtual CPU Interface register offsets */ |
| 57 | #define GICH_CTL 0x0 |
| 58 | #define GICH_VTR 0x4 |
| 59 | #define GICH_ELRSR0 0x30 |
| 60 | #define GICH_ELRSR1 0x34 |
| 61 | #define GICH_APR0 0xF0 |
| 62 | #define GICH_LR_BASE 0x100 |
| 63 | |
| 64 | /* Virtual CPU Interface register offsets */ |
| 65 | #define GICV_CTL 0x0 |
| 66 | #define GICV_PRIMASK 0x4 |
| 67 | #define GICV_BP 0x8 |
| 68 | #define GICV_INTACK 0xC |
| 69 | #define GICV_EOI 0x10 |
| 70 | #define GICV_RUNNINGPRI 0x14 |
| 71 | #define GICV_HIGHESTPEND 0x18 |
| 72 | #define GICV_DEACTIVATE 0x1000 |
| 73 | |
| 74 | /* GICC_IAR bit masks and shifts */ |
| 75 | #define GICC_IAR_INTID_SHIFT 0 |
| 76 | #define GICC_IAR_CPUID_SHIFT 10 |
| 77 | |
| 78 | #define GICC_IAR_INTID_MASK 0x3ff |
| 79 | #define GICC_IAR_CPUID_MASK 0x7 |
| 80 | |
| 81 | #define get_gicc_iar_intid(val) (((val) >> GICC_IAR_INTID_SHIFT) \ |
| 82 | & GICC_IAR_INTID_MASK) |
| 83 | #define get_gicc_iar_cpuid(val) (((val) >> GICC_IAR_CPUID_SHIFT) \ |
| 84 | & GICC_IAR_CPUID_MASK) |
| 85 | |
| 86 | /* |
| 87 | * GICC_CTLR is banked to provide Secure and Non-secure copies and the register |
| 88 | * bit assignments are different in the Secure and Non-secure copies. |
| 89 | * These are the bit assignments for the Non-secure copy. |
| 90 | */ |
| 91 | #define GICC_CTLR_ENABLE (1 << 0) |
| 92 | #define FIQ_BYP_DIS_GRP1 (1 << 5) |
| 93 | #define IRQ_BYP_DIS_GRP1 (1 << 6) |
| 94 | #define EOI_MODE_NS (1 << 9) |
| 95 | |
| 96 | #ifndef __ASSEMBLY__ |
| 97 | |
| 98 | #include <mmio.h> |
| 99 | |
| 100 | /******************************************************************************* |
| 101 | * Private Interfaces for internal use by the GICv2 driver |
| 102 | ******************************************************************************/ |
| 103 | |
| 104 | /******************************************************************************* |
| 105 | * GICv2 Distributor interface accessors for reading/writing entire registers |
| 106 | ******************************************************************************/ |
| 107 | static inline unsigned int gicd_read_sgir(unsigned int base) |
| 108 | { |
| 109 | return mmio_read_32(base + GICD_SGIR); |
| 110 | } |
| 111 | |
| 112 | static inline void gicd_write_sgir(unsigned int base, unsigned int val) |
| 113 | { |
| 114 | mmio_write_32(base + GICD_SGIR, val); |
| 115 | } |
| 116 | |
| 117 | /******************************************************************************* |
| 118 | * GICv2 CPU interface accessors for reading entire registers |
| 119 | ******************************************************************************/ |
| 120 | |
| 121 | static inline unsigned int gicc_read_ctlr(unsigned int base) |
| 122 | { |
| 123 | return mmio_read_32(base + GICC_CTLR); |
| 124 | } |
| 125 | |
| 126 | static inline unsigned int gicc_read_pmr(unsigned int base) |
| 127 | { |
| 128 | return mmio_read_32(base + GICC_PMR); |
| 129 | } |
| 130 | |
| 131 | static inline unsigned int gicc_read_bpr(unsigned int base) |
| 132 | { |
| 133 | return mmio_read_32(base + GICC_BPR); |
| 134 | } |
| 135 | |
| 136 | static inline unsigned int gicc_read_iar(unsigned int base) |
| 137 | { |
| 138 | return mmio_read_32(base + GICC_IAR); |
| 139 | } |
| 140 | |
| 141 | static inline unsigned int gicc_read_eoir(unsigned int base) |
| 142 | { |
| 143 | return mmio_read_32(base + GICC_EOIR); |
| 144 | } |
| 145 | |
| 146 | static inline unsigned int gicc_read_hppir(unsigned int base) |
| 147 | { |
| 148 | return mmio_read_32(base + GICC_HPPIR); |
| 149 | } |
| 150 | |
| 151 | static inline unsigned int gicc_read_ahppir(unsigned int base) |
| 152 | { |
| 153 | return mmio_read_32(base + GICC_AHPPIR); |
| 154 | } |
| 155 | |
| 156 | static inline unsigned int gicc_read_dir(unsigned int base) |
| 157 | { |
| 158 | return mmio_read_32(base + GICC_DIR); |
| 159 | } |
| 160 | |
| 161 | static inline unsigned int gicc_read_iidr(unsigned int base) |
| 162 | { |
| 163 | return mmio_read_32(base + GICC_IIDR); |
| 164 | } |
| 165 | |
| 166 | |
| 167 | /******************************************************************************* |
| 168 | * GICv2 CPU interface accessors for writing entire registers |
| 169 | ******************************************************************************/ |
| 170 | |
| 171 | static inline void gicc_write_ctlr(unsigned int base, unsigned int val) |
| 172 | { |
| 173 | mmio_write_32(base + GICC_CTLR, val); |
| 174 | } |
| 175 | |
| 176 | static inline void gicc_write_pmr(unsigned int base, unsigned int val) |
| 177 | { |
| 178 | mmio_write_32(base + GICC_PMR, val); |
| 179 | } |
| 180 | |
| 181 | static inline void gicc_write_bpr(unsigned int base, unsigned int val) |
| 182 | { |
| 183 | mmio_write_32(base + GICC_BPR, val); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | static inline void gicc_write_iar(unsigned int base, unsigned int val) |
| 188 | { |
| 189 | mmio_write_32(base + GICC_IAR, val); |
| 190 | } |
| 191 | |
| 192 | static inline void gicc_write_eoir(unsigned int base, unsigned int val) |
| 193 | { |
| 194 | mmio_write_32(base + GICC_EOIR, val); |
| 195 | } |
| 196 | |
| 197 | static inline void gicc_write_hppir(unsigned int base, unsigned int val) |
| 198 | { |
| 199 | mmio_write_32(base + GICC_HPPIR, val); |
| 200 | } |
| 201 | |
| 202 | static inline void gicc_write_dir(unsigned int base, unsigned int val) |
| 203 | { |
| 204 | mmio_write_32(base + GICC_DIR, val); |
| 205 | } |
| 206 | |
| 207 | /****************************************************************************** |
| 208 | * GICv2 public driver API |
| 209 | *****************************************************************************/ |
| 210 | |
| 211 | /* |
| 212 | * Initialize the GICv2 driver. The base addresses of GIC CPU interface |
| 213 | * `gicc_base` and the Distributor interface `gicd_base` must be provided |
| 214 | * as arguments. |
| 215 | */ |
| 216 | void gicv2_init(uintptr_t gicc_base, uintptr_t gicd_base); |
| 217 | |
| 218 | /* |
| 219 | * Write the GICv2 EOIR register with `val` passed as argument. `val` |
| 220 | * should be the raw value read from IAR register. |
| 221 | */ |
| 222 | void gicv2_gicc_write_eoir(unsigned int val); |
| 223 | |
| 224 | /* |
| 225 | * Set the bit corresponding to `interrupt_id` in the GICD ISPENDR register. |
| 226 | */ |
| 227 | void gicv2_gicd_set_ispendr(unsigned int interrupt_id); |
| 228 | |
| 229 | /* |
| 230 | * Set the bit corresponding to `interrupt_id` in the GICD ICPENDR register. |
| 231 | */ |
| 232 | void gicv2_gicd_set_icpendr(unsigned int interrupt_id); |
| 233 | |
| 234 | /* |
| 235 | * Get the bit corresponding to `interrupt_id` from the GICD ISPENDR register. |
| 236 | */ |
| 237 | unsigned int gicv2_gicd_get_ispendr(unsigned int interrupt_id); |
| 238 | |
| 239 | /* |
| 240 | * Read and return the value in GICC IAR register |
| 241 | */ |
| 242 | unsigned int gicv2_gicc_read_iar(void); |
| 243 | |
| 244 | /* |
| 245 | * Set the bit corresponding to `num` in the GICD ICENABLER register. |
| 246 | */ |
| 247 | void gicv2_gicd_set_icenabler(unsigned int num); |
| 248 | |
| 249 | /* |
| 250 | * Get the bit corresponding to `num` in the GICD ISENABLER register. |
| 251 | */ |
| 252 | unsigned int gicv2_gicd_get_isenabler(unsigned int num); |
| 253 | |
| 254 | /* |
| 255 | * Set the bit corresponding to `num` in the GICD ISENABLER register. |
| 256 | */ |
| 257 | void gicv2_gicd_set_isenabler(unsigned int num); |
| 258 | |
| 259 | /* |
| 260 | * Set the target of interrupt ID `num` to core with index `core_pos`. |
| 261 | */ |
| 262 | void gicv2_set_itargetsr(unsigned int num, unsigned int core_pos); |
| 263 | |
| 264 | /* |
| 265 | * Set the target of interrupt ID `num` to the desired core mask. |
| 266 | */ |
| 267 | void gicv2_set_itargetsr_value(unsigned int num, unsigned int val); |
| 268 | |
| 269 | /* |
| 270 | * Send SGI with ID `sgi_id` to core with index `core_pos`. |
| 271 | */ |
| 272 | void gicv2_send_sgi(unsigned int sgi_id, unsigned int core_pos); |
| 273 | |
| 274 | /* |
| 275 | * Get the priority of the interrupt `interrupt_id`. |
| 276 | */ |
| 277 | unsigned int gicv2_gicd_get_ipriorityr(unsigned int interrupt_id); |
| 278 | |
| 279 | /* |
| 280 | * Set the priority of the interrupt `interrupt_id` to `priority`. |
| 281 | */ |
| 282 | void gicv2_gicd_set_ipriorityr(unsigned int interrupt_id, unsigned int priority); |
| 283 | |
| 284 | /* |
| 285 | * Setup the GIC Distributor interface. |
| 286 | */ |
| 287 | void gicv2_setup_distif(void); |
| 288 | |
| 289 | /* |
| 290 | * Save the GICv2 SGI and PPI context prior to powering down the |
| 291 | * GIC Distributor. |
| 292 | */ |
| 293 | void gicv2_save_sgi_ppi_context(void); |
| 294 | |
| 295 | /* |
| 296 | * Restore the GICv2 SGI and PPI context after powering up the |
| 297 | * GIC Distributor. |
| 298 | */ |
| 299 | void gicv2_restore_sgi_ppi_context(void); |
| 300 | |
| 301 | /* |
| 302 | * Disable the GIC CPU interface. |
| 303 | */ |
| 304 | void gicv2_disable_cpuif(void); |
| 305 | |
| 306 | /* |
| 307 | * Setup the GIC CPU interface. |
| 308 | */ |
| 309 | void gicv2_setup_cpuif(void); |
| 310 | |
| 311 | /* |
| 312 | * Enable the GIC CPU interface. |
| 313 | */ |
| 314 | void gicv2_enable_cpuif(void); |
| 315 | |
| 316 | /* |
| 317 | * Save the GICv2 CPU interface prior to powering down the CPU interface. |
| 318 | */ |
| 319 | void gicv2_save_cpuif_context(void); |
| 320 | |
| 321 | /* |
| 322 | * Restore the GICv2 CPU interface after powering up the CPU interface. |
| 323 | */ |
| 324 | void gicv2_restore_cpuif_context(void); |
| 325 | |
| 326 | /* |
| 327 | * Read the GICD ITARGETR0 to figure out the GIC ID for the current core. |
| 328 | * This function is required to be invoked on successful boot of a core. |
| 329 | * The GIC ID will be stored internally by the driver to convert core index |
| 330 | * to GIC CPU ID when required. |
| 331 | */ |
| 332 | void gicv2_probe_gic_cpu_id(void); |
| 333 | |
| 334 | |
| 335 | #endif /*__ASSEMBLY__*/ |
| 336 | #endif /* __GIC_V2_H__ */ |