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.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2013, 2019 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifndef LIBBSP_ARM_SHARED_ARM_GIC_H
0038 #define LIBBSP_ARM_SHARED_ARM_GIC_H
0039 
0040 #include <dev/irq/arm-gic-regs.h>
0041 
0042 #include <stdbool.h>
0043 
0044 #ifdef __cplusplus
0045 extern "C" {
0046 #endif /* __cplusplus */
0047 
0048 /**
0049  * @defgroup DevIRQGIC ARM Generic Interrupt Controller (GIC) Support
0050  *
0051  * @ingroup RTEMSImplClassicIntr
0052  *
0053  * @brief This group contains the Interrupt Manager implementation parts
0054  *   specific to the ARM Generic Interrupt Controller.
0055  *
0056  * @{
0057  */
0058 
0059 #define GIC_ID_TO_ONE_BIT_REG_INDEX(id) ((id) >> 5)
0060 #define GIC_ID_TO_ONE_BIT_REG_BIT(id) (1U << ((id) & 0x1fU))
0061 
0062 #define GIC_ID_TO_TWO_BITS_REG_INDEX(id) ((id) >> 4)
0063 #define GIC_ID_TO_TWO_BITS_REG_OFFSET(id) (((id) & 0xfU) << 1)
0064 
0065 static inline bool gic_id_is_enabled(volatile gic_dist *dist, uint32_t id)
0066 {
0067   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0068   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0069 
0070   return (dist->icdiser[i] & bit) != 0;
0071 }
0072 
0073 static inline void gic_id_enable(volatile gic_dist *dist, uint32_t id)
0074 {
0075   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0076   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0077 
0078   dist->icdiser[i] = bit;
0079 }
0080 
0081 static inline void gic_id_disable(volatile gic_dist *dist, uint32_t id)
0082 {
0083   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0084   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0085 
0086   dist->icdicer[i] = bit;
0087 }
0088 
0089 static inline bool gic_id_is_pending(volatile gic_dist *dist, uint32_t id)
0090 {
0091   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0092   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0093 
0094   return (dist->icdispr[i] & bit) != 0;
0095 }
0096 
0097 static inline void gic_id_set_pending(volatile gic_dist *dist, uint32_t id)
0098 {
0099   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0100   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0101 
0102   dist->icdispr[i] = bit;
0103 }
0104 
0105 static inline void gic_id_clear_pending(volatile gic_dist *dist, uint32_t id)
0106 {
0107   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0108   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0109 
0110   dist->icdicpr[i] = bit;
0111 }
0112 
0113 static inline bool gic_id_is_active(volatile gic_dist *dist, uint32_t id)
0114 {
0115   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0116   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0117 
0118   return (dist->icdabr[i] & bit) != 0;
0119 }
0120 
0121 typedef enum {
0122   GIC_GROUP_0,
0123   GIC_GROUP_1
0124 } gic_group;
0125 
0126 static inline gic_group gic_id_get_group(
0127   volatile gic_dist *dist,
0128   uint32_t id
0129 )
0130 {
0131   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0132   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0133 
0134   return (dist->icdigr[i] & bit) != 0 ?  GIC_GROUP_1 : GIC_GROUP_0;
0135 }
0136 
0137 static inline void gic_id_set_group(
0138   volatile gic_dist *dist,
0139   uint32_t id,
0140   gic_group group
0141 )
0142 {
0143   uint32_t i = GIC_ID_TO_ONE_BIT_REG_INDEX(id);
0144   uint32_t bit = GIC_ID_TO_ONE_BIT_REG_BIT(id);
0145   uint32_t icdigr = dist->icdigr[i];
0146 
0147   icdigr &= ~bit;
0148 
0149   if (group == GIC_GROUP_1) {
0150     icdigr |= bit;
0151   }
0152 
0153   dist->icdigr[i] = icdigr;
0154 }
0155 
0156 static inline void gic_id_set_priority(
0157   volatile gic_dist *dist,
0158   uint32_t id,
0159   uint8_t priority
0160 )
0161 {
0162   dist->icdipr[id] = priority;
0163 }
0164 
0165 static inline uint8_t gic_id_get_priority(volatile gic_dist *dist, uint32_t id)
0166 {
0167   return dist->icdipr[id];
0168 }
0169 
0170 static inline void gic_id_set_targets(
0171   volatile gic_dist *dist,
0172   uint32_t id,
0173   uint8_t targets
0174 )
0175 {
0176   dist->icdiptr[id] = targets;
0177 }
0178 
0179 static inline uint8_t gic_id_get_targets(volatile gic_dist *dist, uint32_t id)
0180 {
0181   return dist->icdiptr[id];
0182 }
0183 
0184 typedef enum {
0185   GIC_LEVEL_SENSITIVE,
0186   GIC_EDGE_TRIGGERED
0187 } gic_trigger_mode;
0188 
0189 static inline gic_trigger_mode gic_id_get_trigger_mode(
0190   volatile gic_dist *dist,
0191   uint32_t id
0192 )
0193 {
0194   uint32_t i = GIC_ID_TO_TWO_BITS_REG_INDEX(id);
0195   uint32_t o = GIC_ID_TO_TWO_BITS_REG_OFFSET(id) + 1;
0196   uint32_t bit = 1U << o;
0197 
0198   return (dist->icdicfr[i] & bit) != 0 ?
0199     GIC_EDGE_TRIGGERED : GIC_LEVEL_SENSITIVE;
0200 }
0201 
0202 static inline void gic_id_set_trigger_mode(
0203   volatile gic_dist *dist,
0204   uint32_t id,
0205   gic_trigger_mode mode
0206 )
0207 {
0208   uint32_t i = GIC_ID_TO_TWO_BITS_REG_INDEX(id);
0209   uint32_t o = GIC_ID_TO_TWO_BITS_REG_OFFSET(id) + 1;
0210   uint32_t bit = mode << o;
0211   uint32_t mask = 1U << o;
0212   uint32_t icdicfr = dist->icdicfr[i];
0213 
0214   icdicfr &= ~mask;
0215   icdicfr |= bit;
0216 
0217   dist->icdicfr[i] = icdicfr;
0218 }
0219 
0220 typedef enum {
0221   GIC_N_TO_N,
0222   GIC_1_TO_N
0223 } gic_handling_model;
0224 
0225 static inline gic_handling_model gic_id_get_handling_model(
0226   volatile gic_dist *dist,
0227   uint32_t id
0228 )
0229 {
0230   uint32_t i = GIC_ID_TO_TWO_BITS_REG_INDEX(id);
0231   uint32_t o = GIC_ID_TO_TWO_BITS_REG_OFFSET(id);
0232   uint32_t bit = 1U << o;
0233 
0234   return (dist->icdicfr[i] & bit) != 0 ? GIC_1_TO_N : GIC_N_TO_N;
0235 }
0236 
0237 static inline void gic_id_set_handling_model(
0238   volatile gic_dist *dist,
0239   uint32_t id,
0240   gic_handling_model model
0241 )
0242 {
0243   uint32_t i = GIC_ID_TO_TWO_BITS_REG_INDEX(id);
0244   uint32_t o = GIC_ID_TO_TWO_BITS_REG_OFFSET(id);
0245   uint32_t bit = model << o;
0246   uint32_t mask = 1U << o;
0247   uint32_t icdicfr = dist->icdicfr[i];
0248 
0249   icdicfr &= ~mask;
0250   icdicfr |= bit;
0251 
0252   dist->icdicfr[i] = icdicfr;
0253 }
0254 
0255 /* @} */
0256 
0257 #ifdef __cplusplus
0258 }
0259 #endif /* __cplusplus */
0260 
0261 #endif /* LIBBSP_ARM_SHARED_ARM_GIC_H */