Subversion Repositories AFRtranscoder

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************//**
  2.  * @file     irq_ctrl_gic.c
  3.  * @brief    Interrupt controller handling implementation for GIC
  4.  * @version  V1.0.1
  5.  * @date     9. April 2018
  6.  ******************************************************************************/
  7. /*
  8.  * Copyright (c) 2017 ARM Limited. All rights reserved.
  9.  *
  10.  * SPDX-License-Identifier: Apache-2.0
  11.  *
  12.  * Licensed under the Apache License, Version 2.0 (the License); you may
  13.  * not use this file except in compliance with the License.
  14.  * You may obtain a copy of the License at
  15.  *
  16.  * www.apache.org/licenses/LICENSE-2.0
  17.  *
  18.  * Unless required by applicable law or agreed to in writing, software
  19.  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  20.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21.  * See the License for the specific language governing permissions and
  22.  * limitations under the License.
  23.  */
  24.  
  25. #include <stddef.h>
  26.  
  27. #include "RTE_Components.h"
  28. #include CMSIS_device_header
  29.  
  30. #include "irq_ctrl.h"
  31.  
  32. #if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U)
  33.  
  34. /// Number of implemented interrupt lines
  35. #ifndef IRQ_GIC_LINE_COUNT
  36. #define IRQ_GIC_LINE_COUNT      (1020U)
  37. #endif
  38.  
  39. static IRQHandler_t IRQTable[IRQ_GIC_LINE_COUNT] = { 0U };
  40. static uint32_t     IRQ_ID0;
  41.  
  42. /// Initialize interrupt controller.
  43. __WEAK int32_t IRQ_Initialize (void) {
  44.   uint32_t i;
  45.  
  46.   for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
  47.     IRQTable[i] = (IRQHandler_t)NULL;
  48.   }
  49.   GIC_Enable();
  50.   return (0);
  51. }
  52.  
  53.  
  54. /// Register interrupt handler.
  55. __WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
  56.   int32_t status;
  57.  
  58.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  59.     IRQTable[irqn] = handler;
  60.     status =  0;
  61.   } else {
  62.     status = -1;
  63.   }
  64.  
  65.   return (status);
  66. }
  67.  
  68.  
  69. /// Get the registered interrupt handler.
  70. __WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
  71.   IRQHandler_t h;
  72.  
  73.   // Ignore CPUID field (software generated interrupts)
  74.   irqn &= 0x3FFU;
  75.  
  76.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  77.     h = IRQTable[irqn];
  78.   } else {
  79.     h = (IRQHandler_t)0;
  80.   }
  81.  
  82.   return (h);
  83. }
  84.  
  85.  
  86. /// Enable interrupt.
  87. __WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) {
  88.   int32_t status;
  89.  
  90.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  91.     GIC_EnableIRQ ((IRQn_Type)irqn);
  92.     status = 0;
  93.   } else {
  94.     status = -1;
  95.   }
  96.  
  97.   return (status);
  98. }
  99.  
  100.  
  101. /// Disable interrupt.
  102. __WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) {
  103.   int32_t status;
  104.  
  105.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  106.     GIC_DisableIRQ ((IRQn_Type)irqn);
  107.     status = 0;
  108.   } else {
  109.     status = -1;
  110.   }
  111.  
  112.   return (status);
  113. }
  114.  
  115.  
  116. /// Get interrupt enable state.
  117. __WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
  118.   uint32_t enable;
  119.  
  120.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  121.     enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
  122.   } else {
  123.     enable = 0U;
  124.   }
  125.  
  126.   return (enable);
  127. }
  128.  
  129.  
  130. /// Configure interrupt request mode.
  131. __WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
  132.   uint32_t val;
  133.   uint8_t cfg;
  134.   uint8_t secure;
  135.   uint8_t cpu;
  136.   int32_t status = 0;
  137.  
  138.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  139.     // Check triggering mode
  140.     val = (mode & IRQ_MODE_TRIG_Msk);
  141.  
  142.     if (val == IRQ_MODE_TRIG_LEVEL) {
  143.       cfg = 0x00U;
  144.     } else if (val == IRQ_MODE_TRIG_EDGE) {
  145.       cfg = 0x02U;
  146.     } else {
  147.       cfg = 0x00U;
  148.       status = -1;
  149.     }
  150.  
  151.     // Check interrupt type
  152.     val = mode & IRQ_MODE_TYPE_Msk;
  153.  
  154.     if (val != IRQ_MODE_TYPE_IRQ) {
  155.       status = -1;
  156.     }
  157.  
  158.     // Check interrupt domain
  159.     val = mode & IRQ_MODE_DOMAIN_Msk;
  160.  
  161.     if (val == IRQ_MODE_DOMAIN_NONSECURE) {
  162.       secure = 0U;
  163.     } else {
  164.       // Check security extensions support
  165.       val = GIC_DistributorInfo() & (1UL << 10U);
  166.  
  167.       if (val != 0U) {
  168.         // Security extensions are supported
  169.         secure = 1U;
  170.       } else {
  171.         secure = 0U;
  172.         status = -1;
  173.       }
  174.     }
  175.  
  176.     // Check interrupt CPU targets
  177.     val = mode & IRQ_MODE_CPU_Msk;
  178.  
  179.     if (val == IRQ_MODE_CPU_ALL) {
  180.       cpu = 0xFFU;
  181.     } else {
  182.       cpu = val >> IRQ_MODE_CPU_Pos;
  183.     }
  184.  
  185.     // Apply configuration if no mode error
  186.     if (status == 0) {
  187.       GIC_SetConfiguration((IRQn_Type)irqn, cfg);
  188.       GIC_SetTarget       ((IRQn_Type)irqn, cpu);
  189.  
  190.       if (secure != 0U) {
  191.         GIC_SetGroup ((IRQn_Type)irqn, secure);
  192.       }
  193.     }
  194.   }
  195.  
  196.   return (status);
  197. }
  198.  
  199.  
  200. /// Get interrupt mode configuration.
  201. __WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
  202.   uint32_t mode;
  203.   uint32_t val;
  204.  
  205.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  206.     mode = IRQ_MODE_TYPE_IRQ;
  207.  
  208.     // Get trigger mode
  209.     val = GIC_GetConfiguration((IRQn_Type)irqn);
  210.  
  211.     if ((val & 2U) != 0U) {
  212.       // Corresponding interrupt is edge triggered
  213.       mode |= IRQ_MODE_TRIG_EDGE;
  214.     } else {
  215.       // Corresponding interrupt is level triggered
  216.       mode |= IRQ_MODE_TRIG_LEVEL;
  217.     }
  218.  
  219.     // Get interrupt CPU targets
  220.     mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
  221.  
  222.   } else {
  223.     mode = IRQ_MODE_ERROR;
  224.   }
  225.  
  226.   return (mode);
  227. }
  228.  
  229.  
  230. /// Get ID number of current interrupt request (IRQ).
  231. __WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) {
  232.   IRQn_ID_t irqn;
  233.   uint32_t prio;
  234.  
  235.   /* Dummy read to avoid GIC 390 errata 801120 */
  236.   GIC_GetHighPendingIRQ();
  237.  
  238.   irqn = GIC_AcknowledgePending();
  239.  
  240.   __DSB();
  241.  
  242.   /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014)  */
  243.   /* The following workaround code is for a single-core system.  It would be       */
  244.   /* different in a multi-core system.                                             */
  245.   /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
  246.   /* so unlock it, otherwise service the interrupt as normal.                      */
  247.   /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2  */
  248.   /* so will not occur here.                                                       */
  249.  
  250.   if ((irqn == 0) || (irqn >= 0x3FE)) {
  251.     /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
  252.     prio = GIC_GetPriority((IRQn_Type)0);
  253.     GIC_SetPriority ((IRQn_Type)0, prio);
  254.  
  255.     __DSB();
  256.  
  257.     if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) {
  258.       /* If the ID is 0, is active and has not been seen before */
  259.       IRQ_ID0 = 1U;
  260.     }
  261.     /* End of Workaround GIC 390 errata 733075 */
  262.   }
  263.  
  264.   return (irqn);
  265. }
  266.  
  267.  
  268. /// Get ID number of current fast interrupt request (FIQ).
  269. __WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) {
  270.   return ((IRQn_ID_t)-1);
  271. }
  272.  
  273.  
  274. /// Signal end of interrupt processing.
  275. __WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
  276.   int32_t status;
  277.   IRQn_Type irq = (IRQn_Type)irqn;
  278.  
  279.   irqn &= 0x3FFU;
  280.  
  281.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  282.     GIC_EndInterrupt (irq);
  283.  
  284.     if (irqn == 0) {
  285.       IRQ_ID0 = 0U;
  286.     }
  287.  
  288.     status = 0;
  289.   } else {
  290.     status = -1;
  291.   }
  292.  
  293.   return (status);
  294. }
  295.  
  296.  
  297. /// Set interrupt pending flag.
  298. __WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) {
  299.   int32_t status;
  300.  
  301.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  302.     GIC_SetPendingIRQ ((IRQn_Type)irqn);
  303.     status = 0;
  304.   } else {
  305.     status = -1;
  306.   }
  307.  
  308.   return (status);
  309. }
  310.  
  311. /// Get interrupt pending flag.
  312. __WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
  313.   uint32_t pending;
  314.  
  315.   if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  316.     pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
  317.   } else {
  318.     pending = 0U;
  319.   }
  320.  
  321.   return (pending & 1U);
  322. }
  323.  
  324.  
  325. /// Clear interrupt pending flag.
  326. __WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
  327.   int32_t status;
  328.  
  329.   if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  330.     GIC_ClearPendingIRQ ((IRQn_Type)irqn);
  331.     status = 0;
  332.   } else {
  333.     status = -1;
  334.   }
  335.  
  336.   return (status);
  337. }
  338.  
  339.  
  340. /// Set interrupt priority value.
  341. __WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
  342.   int32_t status;
  343.  
  344.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  345.     GIC_SetPriority ((IRQn_Type)irqn, priority);
  346.     status = 0;
  347.   } else {
  348.     status = -1;
  349.   }
  350.  
  351.   return (status);
  352. }
  353.  
  354.  
  355. /// Get interrupt priority.
  356. __WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
  357.   uint32_t priority;
  358.  
  359.   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
  360.     priority = GIC_GetPriority ((IRQn_Type)irqn);
  361.   } else {
  362.     priority = IRQ_PRIORITY_ERROR;
  363.   }
  364.  
  365.   return (priority);
  366. }
  367.  
  368.  
  369. /// Set priority masking threshold.
  370. __WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) {
  371.   GIC_SetInterfacePriorityMask (priority);
  372.   return (0);
  373. }
  374.  
  375.  
  376. /// Get priority masking threshold
  377. __WEAK uint32_t IRQ_GetPriorityMask (void) {
  378.   return GIC_GetInterfacePriorityMask();
  379. }
  380.  
  381.  
  382. /// Set priority grouping field split point
  383. __WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
  384.   int32_t status;
  385.  
  386.   if (bits == IRQ_PRIORITY_Msk) {
  387.     bits = 7U;
  388.   }
  389.  
  390.   if (bits < 8U) {
  391.     GIC_SetBinaryPoint (7U - bits);
  392.     status = 0;
  393.   } else {
  394.     status = -1;
  395.   }
  396.  
  397.   return (status);
  398. }
  399.  
  400.  
  401. /// Get priority grouping field split point
  402. __WEAK uint32_t IRQ_GetPriorityGroupBits (void) {
  403.   uint32_t bp;
  404.  
  405.   bp = GIC_GetBinaryPoint() & 0x07U;
  406.  
  407.   return (7U - bp);
  408. }
  409.  
  410. #endif
  411.