Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:42

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup DevIRQGIC
0007  *
0008  * @brief This header file provides interfaces of the ARM Generic Interrupt
0009  *   Controller (GIC) support specific to the GICv3.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2022 embedded brains GmbH & Co. KG
0014  * Copyright (C) 2019 On-Line Applications Research Corporation (OAR)
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_DEV_IRQ_ARM_GICV3_H
0039 #define _RTEMS_DEV_IRQ_ARM_GICV3_H
0040 
0041 #include <dev/irq/arm-gic.h>
0042 #include <dev/irq/arm-gic-arch.h>
0043 
0044 #ifdef __cplusplus
0045 extern "C" {
0046 #endif
0047 
0048 /**
0049  * @addtogroup DevIRQGIC
0050  *
0051  * @{
0052  */
0053 
0054 #define PRIORITY_DEFAULT 127
0055 
0056 #define MPIDR_AFFINITY2(val) BSP_FLD64(val, 16, 23)
0057 #define MPIDR_AFFINITY2_GET(reg) BSP_FLD64GET(reg, 16, 23)
0058 #define MPIDR_AFFINITY2_SET(reg, val) BSP_FLD64SET(reg, val, 16, 23)
0059 #define MPIDR_AFFINITY1(val) BSP_FLD64(val, 8, 15)
0060 #define MPIDR_AFFINITY1_GET(reg) BSP_FLD64GET(reg, 8, 15)
0061 #define MPIDR_AFFINITY1_SET(reg, val) BSP_FLD64SET(reg, val, 8, 15)
0062 #define MPIDR_AFFINITY0(val) BSP_FLD64(val, 0, 7)
0063 #define MPIDR_AFFINITY0_GET(reg) BSP_FLD64GET(reg, 0, 7)
0064 #define MPIDR_AFFINITY0_SET(reg, val) BSP_FLD64SET(reg, val, 0, 7)
0065 
0066 #define ICC_SGIR_AFFINITY3(val) BSP_FLD64(val, 48, 55)
0067 #define ICC_SGIR_AFFINITY3_GET(reg) BSP_FLD64GET(reg, 48, 55)
0068 #define ICC_SGIR_AFFINITY3_SET(reg, val) BSP_FLD64SET(reg, val, 48, 55)
0069 #define ICC_SGIR_IRM BSP_BIT32(40)
0070 #define ICC_SGIR_AFFINITY2(val) BSP_FLD64(val, 32, 39)
0071 #define ICC_SGIR_AFFINITY2_GET(reg) BSP_FLD64GET(reg, 32, 39)
0072 #define ICC_SGIR_AFFINITY2_SET(reg, val) BSP_FLD64SET(reg, val, 32, 39)
0073 #define ICC_SGIR_INTID(val) BSP_FLD64(val, 24, 27)
0074 #define ICC_SGIR_INTID_GET(reg) BSP_FLD64GET(reg, 24, 27)
0075 #define ICC_SGIR_INTID_SET(reg, val) BSP_FLD64SET(reg, val, 24, 27)
0076 #define ICC_SGIR_AFFINITY1(val) BSP_FLD64(val, 16, 23)
0077 #define ICC_SGIR_AFFINITY1_GET(reg) BSP_FLD64GET(reg, 16, 23)
0078 #define ICC_SGIR_AFFINITY1_SET(reg, val) BSP_FLD64SET(reg, val, 16, 23)
0079 #define ICC_SGIR_CPU_TARGET_LIST(val) BSP_FLD64(val, 0, 15)
0080 #define ICC_SGIR_CPU_TARGET_LIST_GET(reg) BSP_FLD64GET(reg, 0, 15)
0081 #define ICC_SGIR_CPU_TARGET_LIST_SET(reg, val) BSP_FLD64SET(reg, val, 0, 15)
0082 
0083 #ifdef ARM_MULTILIB_ARCH_V4
0084 /* cpuif->iccicr */
0085 #define ICC_CTLR    "p15, 0, %0, c12, c12, 4"
0086 
0087 /* cpuif->iccpmr */
0088 #define ICC_PMR     "p15, 0, %0,  c4,  c6, 0"
0089 
0090 /* cpuif->iccbpr */
0091 #define ICC_BPR0    "p15, 0, %0, c12,  c8, 3"
0092 #define ICC_BPR1    "p15, 0, %0, c12, c12, 3"
0093 
0094 /* cpuif->icciar */
0095 #define ICC_IAR0    "p15, 0, %0, c12,  c8, 0"
0096 #define ICC_IAR1    "p15, 0, %0, c12, c12, 0"
0097 
0098 /* cpuif->icceoir */
0099 #define ICC_EOIR0   "p15, 0, %0, c12,  c8, 1"
0100 #define ICC_EOIR1   "p15, 0, %0, c12, c12, 1"
0101 
0102 #define ICC_SRE     "p15, 0, %0, c12, c12, 5"
0103 
0104 #define ICC_IGRPEN0 "p15, 0, %0, c12, c12, 6"
0105 #define ICC_IGRPEN1 "p15, 0, %0, c12, c12, 7"
0106 
0107 #define MPIDR       "p15, 0, %0, c0, c0, 5"
0108 
0109 #define READ_SR(SR_NAME) \
0110 ({ \
0111   uint32_t value; \
0112   __asm__ volatile("mrc    " SR_NAME : "=r" (value) ); \
0113   value; \
0114 })
0115 
0116 #define WRITE_SR(SR_NAME, VALUE) \
0117     __asm__ volatile("mcr    " SR_NAME "  \n" : : "r" (VALUE) );
0118 
0119 #define ICC_SGI1    "p15, 0, %Q0, %R0, c12"
0120 #define WRITE64_SR(SR_NAME, VALUE) \
0121     __asm__ volatile("mcrr    " SR_NAME "  \n" : : "r" (VALUE) );
0122 
0123 #else /* ARM_MULTILIB_ARCH_V4 */
0124 
0125 /* AArch64 GICv3 registers are not named in GCC */
0126 #define ICC_IGRPEN0_EL1 "S3_0_C12_C12_6, %0"
0127 #define ICC_IGRPEN1_EL1 "S3_0_C12_C12_7, %0"
0128 #define ICC_IGRPEN1_EL3 "S3_6_C12_C12_7, %0"
0129 #define ICC_IGRPEN0 ICC_IGRPEN0_EL1
0130 #define ICC_IGRPEN1 ICC_IGRPEN1_EL1
0131 #define ICC_PMR     "S3_0_C4_C6_0, %0"
0132 #define ICC_EOIR1   "S3_0_C12_C12_1, %0"
0133 #define ICC_SRE     "S3_0_C12_C12_5, %0"
0134 #define ICC_BPR0    "S3_0_C12_C8_3, %0"
0135 #define ICC_BPR1    "S3_0_C12_C12_3, %0"
0136 #define ICC_CTLR    "S3_0_C12_C12_4, %0"
0137 #define ICC_IAR1    "%0, S3_0_C12_C12_0"
0138 #define MPIDR       "%0, mpidr_el1"
0139 #define MPIDR_AFFINITY3(val) BSP_FLD64(val, 32, 39)
0140 #define MPIDR_AFFINITY3_GET(reg) BSP_FLD64GET(reg, 32, 39)
0141 #define MPIDR_AFFINITY3_SET(reg, val) BSP_FLD64SET(reg, val, 32, 39)
0142 
0143 #define ICC_SGI1    "S3_0_C12_C11_5, %0"
0144 #define WRITE64_SR(SR_NAME, VALUE) \
0145     __asm__ volatile("msr    " SR_NAME "  \n" : : "r" (VALUE) );
0146 #define WRITE_SR(SR_NAME, VALUE) WRITE64_SR(SR_NAME, VALUE)
0147 
0148 #define READ_SR(SR_NAME) \
0149 ({ \
0150   uint64_t value; \
0151   __asm__ volatile("mrs    " SR_NAME : "=&r" (value) ); \
0152   value; \
0153 })
0154 
0155 #endif /* ARM_MULTILIB_ARCH_V4 */
0156 
0157 static inline volatile gic_redist *gicv3_get_redist(uint32_t cpu_index)
0158 {
0159   return (volatile gic_redist *)
0160     ((uintptr_t)BSP_ARM_GIC_REDIST_BASE + cpu_index * 0x20000);
0161 }
0162 
0163 static inline volatile gic_sgi_ppi *gicv3_get_sgi_ppi(uint32_t cpu_index)
0164 {
0165   return (volatile gic_sgi_ppi *)
0166     ((uintptr_t)BSP_ARM_GIC_REDIST_BASE + cpu_index * 0x20000 + 0x10000);
0167 }
0168 
0169 static inline void gicv3_sgi_ppi_enable(
0170   rtems_vector_number vector,
0171   uint32_t            cpu_index
0172 )
0173 {
0174   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0175 
0176   /* Set G1NS */
0177   sgi_ppi->icspigrpr[0] |= 1U << vector;
0178   sgi_ppi->icspigrpmodr[0] &= ~(1U << vector);
0179 
0180   /* Set enable */
0181   sgi_ppi->icspiser[0] = 1U << vector;
0182 }
0183 
0184 static inline void gicv3_sgi_ppi_disable(
0185   rtems_vector_number vector,
0186   uint32_t            cpu_index
0187 )
0188 {
0189   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0190 
0191   sgi_ppi->icspicer[0] = 1U << vector;
0192 }
0193 
0194 static inline bool gicv3_sgi_ppi_is_enabled(
0195   rtems_vector_number vector,
0196   uint32_t            cpu_index
0197 )
0198 {
0199   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0200 
0201   return (sgi_ppi->icspiser[0] & (1U << vector)) != 0;
0202 }
0203 
0204 static inline void gicv3_sgi_ppi_set_priority(
0205   rtems_vector_number vector,
0206   uint8_t             priority,
0207   uint32_t            cpu_index
0208 )
0209 {
0210   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0211 
0212   sgi_ppi->icspiprior[vector] = priority;
0213 }
0214 
0215 static inline uint8_t gicv3_sgi_ppi_get_priority(
0216   rtems_vector_number vector,
0217   uint32_t            cpu_index
0218 )
0219 {
0220   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0221 
0222   return sgi_ppi->icspiprior[vector];
0223 }
0224 
0225 static inline bool gicv3_sgi_ppi_is_pending(
0226   rtems_vector_number vector,
0227   uint32_t            cpu_index
0228 )
0229 {
0230   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0231 
0232   return (sgi_ppi->icspispendr[0] & (1U << vector)) != 0;
0233 }
0234 
0235 static inline void gicv3_ppi_set_pending(
0236   rtems_vector_number vector,
0237   uint32_t            cpu_index
0238 )
0239 {
0240   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0241 
0242   sgi_ppi->icspispendr[0] = 1U << vector;
0243 }
0244 
0245 static inline void gicv3_ppi_clear_pending(
0246   rtems_vector_number vector,
0247   uint32_t            cpu_index
0248 )
0249 {
0250   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0251 
0252   sgi_ppi->icspicpendr[0] = 1U << vector;
0253 }
0254 
0255 static inline void gicv3_trigger_sgi(
0256   rtems_vector_number vector,
0257   uint32_t            targets
0258 )
0259 {
0260 #ifndef ARM_MULTILIB_ARCH_V4
0261   uint64_t mpidr;
0262 #else
0263   uint32_t mpidr;
0264 #endif
0265   mpidr = READ_SR(MPIDR);
0266   uint64_t value = ICC_SGIR_AFFINITY2(MPIDR_AFFINITY2_GET(mpidr))
0267                  | ICC_SGIR_INTID(vector)
0268                  | ICC_SGIR_AFFINITY1(MPIDR_AFFINITY1_GET(mpidr))
0269                  | ICC_SGIR_CPU_TARGET_LIST(targets);
0270 #ifndef ARM_MULTILIB_ARCH_V4
0271   value |= ICC_SGIR_AFFINITY3(MPIDR_AFFINITY3_GET(mpidr));
0272 #endif
0273   WRITE64_SR(ICC_SGI1, value);
0274 }
0275 
0276 static inline uint32_t gicv3_get_id_count(volatile gic_dist *dist)
0277 {
0278   uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr);
0279 
0280   id_count = 32 * (id_count + 1);
0281   id_count = id_count <= 1020 ? id_count : 1020;
0282 
0283   return id_count;
0284 }
0285 
0286 static void gicv3_init_dist(volatile gic_dist *dist)
0287 {
0288   uint32_t id_count = gicv3_get_id_count(dist);
0289   uint32_t id;
0290 
0291   dist->icddcr = GIC_DIST_ICDDCR_ARE_NS | GIC_DIST_ICDDCR_ARE_S
0292                | GIC_DIST_ICDDCR_ENABLE_GRP1S | GIC_DIST_ICDDCR_ENABLE_GRP1NS
0293                | GIC_DIST_ICDDCR_ENABLE_GRP0;
0294 
0295   for (id = 0; id < id_count; id += 32) {
0296     /* Disable all interrupts */
0297     dist->icdicer[id / 32] = 0xffffffff;
0298 
0299     /* Set G1NS */
0300     dist->icdigr[id / 32] = 0xffffffff;
0301     dist->icdigmr[id / 32] = 0;
0302   }
0303 
0304   for (id = 0; id < id_count; ++id) {
0305     gic_id_set_priority(dist, id, PRIORITY_DEFAULT);
0306   }
0307 
0308   for (id = 32; id < id_count; ++id) {
0309     gic_id_set_targets(dist, id, 0x01);
0310   }
0311 }
0312 
0313 static void gicv3_init_cpu_interface(uint32_t cpu_index)
0314 {
0315   /* Initialize Interrupt Controller System Register Enable Register */
0316 #ifdef BSP_ARM_GIC_ICC_SRE
0317   WRITE_SR(ICC_SRE, BSP_ARM_GIC_ICC_SRE);
0318 #endif
0319 
0320   /* Initialize Interrupt Controller Interrupt Priority Mask Register */
0321 #ifdef BSP_ARM_GIC_ICC_PMR
0322   WRITE_SR(ICC_PMR, BSP_ARM_GIC_ICC_PMR);
0323 #endif
0324 
0325   /* Initialize Interrupt Controller Binary Point Register 0 */
0326 #ifdef BSP_ARM_GIC_ICC_BPR0
0327   WRITE_SR(ICC_BPR0, BSP_ARM_GIC_ICC_BPR0);
0328 #endif
0329 
0330   /* Initialize Interrupt Controller Binary Point Register 1 */
0331 #ifdef BSP_ARM_GIC_ICC_BPR1
0332   WRITE_SR(ICC_BPR1, BSP_ARM_GIC_ICC_BPR1);
0333 #endif
0334 
0335   volatile gic_redist *redist = gicv3_get_redist(cpu_index);
0336   uint32_t waker = redist->icrwaker;
0337   uint32_t waker_mask = GIC_REDIST_ICRWAKER_PROCESSOR_SLEEP;
0338   waker &= ~waker_mask;
0339   redist->icrwaker = waker;
0340 
0341   volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(cpu_index);
0342   /* Set G1NS */
0343   sgi_ppi->icspigrpr[0] = 0xffffffff;
0344   sgi_ppi->icspigrpmodr[0] = 0;
0345   for (int id = 0; id < 32; id++) {
0346     sgi_ppi->icspiprior[id] = PRIORITY_DEFAULT;
0347   }
0348 
0349   /* Initialize Interrupt Controller Interrupt Group Enable 0 Register */
0350 #ifdef BSP_ARM_GIC_ICC_IGRPEN0
0351   WRITE_SR(ICC_IGRPEN0, BSP_ARM_GIC_ICC_IGRPEN0);
0352 #endif
0353 
0354   /* Initialize Interrupt Controller Interrupt Group Enable 1 Register */
0355 #ifdef BSP_ARM_GIC_ICC_IGRPEN1
0356   WRITE_SR(ICC_IGRPEN1, BSP_ARM_GIC_ICC_IGRPEN1);
0357 #endif
0358 
0359   /* Initialize Interrupt Controller Control Register */
0360 #ifdef BSP_ARM_GIC_ICC_CTRL
0361   WRITE_SR(ICC_CTLR, BSP_ARM_GIC_ICC_CTRL);
0362 #endif
0363 }
0364 
0365 static inline void gicv3_get_attributes(
0366   rtems_vector_number         vector,
0367   rtems_interrupt_attributes *attributes
0368 )
0369 {
0370   attributes->is_maskable = true;
0371   attributes->maybe_enable = true;
0372   attributes->maybe_disable = true;
0373   attributes->can_raise = true;
0374   attributes->can_get_priority = true;
0375   attributes->can_set_priority = true;
0376   attributes->maximum_priority = 255;
0377 
0378   if ( vector <= ARM_GIC_IRQ_SGI_LAST ) {
0379     /*
0380      * It is implementation-defined whether implemented SGIs are permanently
0381      * enabled, or can be enabled and disabled by writes to GICD_ISENABLER0 and
0382      * GICD_ICENABLER0.
0383      */
0384     attributes->can_raise_on = true;
0385     attributes->cleared_by_acknowledge = true;
0386     attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
0387   } else {
0388     attributes->can_disable = true;
0389     attributes->can_clear = true;
0390     attributes->trigger_signal = RTEMS_INTERRUPT_UNSPECIFIED_SIGNAL;
0391 
0392     if ( vector > ARM_GIC_IRQ_PPI_LAST ) {
0393       /* SPI */
0394       attributes->can_get_affinity = true;
0395       attributes->can_set_affinity = true;
0396     }
0397   }
0398 }
0399 
0400 /** @} */
0401 
0402 #ifdef __cplusplus
0403 }
0404 #endif
0405 
0406 #endif /* _RTEMS_DEV_IRQ_ARM_GICV3_H */