Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * RTEMS virtex BSP
0005  *
0006  * This file contains the irq controller handler.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2007 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 #include <libcpu/spr.h>
0035 #include <bsp/irq.h>
0036 #include <bsp.h>
0037 #include <rtems/bspIo.h>
0038 #include <rtems/powerpc/powerpc.h>
0039 #include <bsp/vectors.h>
0040 
0041 static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER];
0042 rtems_irq_connect_data *BSP_rtems_irq_tbl;
0043 rtems_irq_global_settings* BSP_rtems_irq_config;
0044 
0045 /***********************************************************
0046  * dummy functions for on/off/isOn calls
0047  * these functions just do nothing fulfill the semantic
0048  * requirements to enable/disable a certain interrupt or exception
0049  */
0050 static void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
0051 {
0052   /*
0053    * nothing to do
0054    */
0055 }
0056 
0057 static void BSP_irq_nop_hdl(void *hdl)
0058 {
0059   /*
0060    * nothing to do
0061    */
0062 }
0063 
0064 static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
0065 {
0066   /*
0067    * nothing to do
0068    */
0069   return 0;
0070 }
0071 
0072 /***********************************************************
0073  * interrupt handler and its enable/disable functions
0074  ***********************************************************/
0075 
0076 /***********************************************************
0077  * functions to enable/disable/query external/critical interrupts
0078  */
0079 void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data)
0080 {
0081   uint32_t msr_value;
0082   /*
0083    * get current MSR value
0084    */
0085   _CPU_MSR_GET(msr_value);
0086 
0087   msr_value |= PPC_MSR_EE;
0088   _CPU_MSR_SET(msr_value);
0089 }
0090 
0091 void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused)
0092 {
0093   uint32_t msr_value;
0094   /*
0095    * get current MSR value
0096    */
0097   _CPU_MSR_GET(msr_value);
0098 
0099   msr_value &= ~PPC_MSR_EE;
0100   _CPU_MSR_SET(msr_value);
0101 }
0102 
0103 /***********************************************************
0104  * High level IRQ handler called from shared_raw_irq_code_entry
0105  */
0106 static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
0107 {
0108   /*
0109    * Handle interrupt
0110    */
0111   switch(excNum) {
0112   case ASM_EXT_VECTOR:
0113     BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
0114     break;
0115   case ASM_BOOKE_DEC_VECTOR:
0116     BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle);
0117     break;
0118 #if 0 /* Critical interrupts not yet supported */
0119   case ASM_BOOKE_CRIT_VECTOR:
0120     BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
0121     break;
0122 #endif
0123   }
0124 
0125   return 0;
0126 }
0127 
0128 /***********************************************************
0129  * functions to set/get/remove interrupt handlers
0130  ***********************************************************/
0131 int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
0132 {
0133   rtems_interrupt_level level;
0134 
0135   /*
0136    * check for valid irq name
0137    * if invalid, print error and return 0
0138    */
0139   if (!BSP_IS_VALID_IRQ(irq->name)) {
0140     printk("Invalid interrupt vector %d\n",irq->name);
0141     return 0;
0142   }
0143 
0144   /*
0145    * disable interrupts
0146    */
0147   rtems_interrupt_disable(level);
0148 
0149   /*
0150    * check, that default handler is installed now
0151    */
0152   if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) {
0153     rtems_interrupt_enable(level);
0154     printk("IRQ vector %d already connected\n",irq->name);
0155     return 0;
0156   }
0157 
0158   /*
0159    * store new handler data
0160    */
0161   rtemsIrqTbl[irq->name] = *irq;
0162 
0163   /*
0164    * call "on" function to enable interrupt at device
0165    */
0166   irq->on(irq);
0167 
0168   /*
0169    * reenable interrupts
0170    */
0171   rtems_interrupt_enable(level);
0172 
0173   return 1;
0174 }
0175 
0176 int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
0177 {
0178   rtems_interrupt_level level;
0179 
0180   /*
0181    * check for valid IRQ name
0182    */
0183   if (!BSP_IS_VALID_IRQ(irq->name)) {
0184     return 0;
0185   }
0186   rtems_interrupt_disable(level);
0187 
0188   /*
0189    * return current IRQ entry
0190    */
0191   *irq = rtemsIrqTbl[irq->name];
0192   rtems_interrupt_enable(level);
0193   return 1;
0194 }
0195 
0196 int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
0197 {
0198   rtems_interrupt_level level;
0199 
0200   /*
0201    * check for valid IRQ name
0202    */
0203   if (!BSP_IS_VALID_IRQ(irq->name)) {
0204     return 0;
0205   }
0206   rtems_interrupt_disable(level);
0207 
0208   /*
0209    * check, that specified handler is really connected now
0210    */
0211   if (rtemsIrqTbl[irq->name].hdl != irq->hdl) {
0212     rtems_interrupt_enable(level);
0213     return 0;
0214   }
0215 
0216   /*
0217    * disable interrupt at source
0218    */
0219   irq->off(irq);
0220 
0221   /*
0222    * restore default interrupt handler
0223    */
0224   rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry;
0225 
0226   /*
0227    * reenable interrupts
0228    */
0229   rtems_interrupt_enable(level);
0230 
0231   return 1;
0232 }
0233 
0234 /***********************************************************
0235  * functions to set/get the basic interrupt management setup
0236  ***********************************************************/
0237 /*
0238  * (Re) get info on current RTEMS interrupt management.
0239  */
0240 int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr)
0241 {
0242   *ret_ptr = BSP_rtems_irq_config;
0243   return 0;
0244 }
0245 
0246 
0247 /*
0248  * set management stuff
0249  */
0250 int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
0251 {
0252   int                    i;
0253   rtems_interrupt_level  level;
0254 
0255   rtems_interrupt_disable(level);
0256 
0257   /*
0258    * store given configuration
0259    */
0260   BSP_rtems_irq_config = config;
0261   BSP_rtems_irq_tbl    = BSP_rtems_irq_config->irqHdlTbl;
0262 
0263   /*
0264    * store any irq-like processor exceptions
0265    */
0266   for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
0267        i < BSP_PROCESSOR_IRQ_MAX_OFFSET;
0268        i++) {
0269     if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
0270       if (BSP_rtems_irq_tbl[i].on != NULL) {
0271     BSP_rtems_irq_tbl[i].on
0272       (&(BSP_rtems_irq_tbl[i]));
0273       }
0274     }
0275     else {
0276       if (BSP_rtems_irq_tbl[i].off != NULL) {
0277     BSP_rtems_irq_tbl[i].off
0278       (&(BSP_rtems_irq_tbl[i]));
0279       }
0280     }
0281   }
0282   rtems_interrupt_enable(level);
0283   return 1;
0284 }
0285 
0286 /*
0287  * dummy for an empty IRQ handler entry
0288  */
0289 static rtems_irq_connect_data emptyIrq = {
0290   0,                 /* IRQ Name                 */
0291   BSP_irq_nop_hdl,       /* handler function         */
0292   NULL,                  /* handle passed to handler */
0293   BSP_irq_nop_func,      /* on function              */
0294   BSP_irq_nop_func,      /* off function             */
0295   BSP_irq_isOn_func      /* isOn function            */
0296 };
0297 
0298 static rtems_irq_global_settings initialConfig = {
0299   BSP_IRQ_NUMBER,           /* IRQ Number               */
0300   {  0,             /* IRQ Name                 */
0301      BSP_irq_nop_hdl,       /* handler function         */
0302      NULL,                  /* handle passed to handler */
0303      BSP_irq_nop_func,      /* on function              */
0304      BSP_irq_nop_func,      /* off function             */
0305      BSP_irq_isOn_func      /* isOn function            */
0306   }, /* emptyIrq */
0307   rtemsIrqTbl, /* irqHdlTbl  */
0308   0,           /* irqBase    */
0309   NULL         /* irqPrioTbl */
0310 };
0311 
0312 void BSP_rtems_irq_mngt_init(unsigned cpuId)
0313 {
0314   int i;
0315 
0316   /*
0317    * connect all exception vectors needed
0318    */
0319   ppc_exc_set_handler(ASM_EXT_VECTOR,       C_dispatch_irq_handler);
0320   ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler);
0321 
0322   /*
0323    * setup interrupt handlers table
0324    */
0325   for (i = 0;
0326        i < BSP_IRQ_NUMBER;
0327        i++) {
0328     rtemsIrqTbl[i]      = emptyIrq;
0329     rtemsIrqTbl[i].name = i;
0330   }
0331 
0332   /*
0333    * initialize interrupt management
0334    */
0335   if (!BSP_rtems_irq_mngt_set(&initialConfig)) {
0336     rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
0337   }
0338 }