Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:00

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 SPR_RW(BOOKE_TSR)
0104 
0105 static int C_dispatch_dec_handler (BSP_Exception_frame *frame, unsigned int excNum)
0106 {
0107   /* Acknowledge the interrupt */
0108   _write_BOOKE_TSR( BOOKE_TSR_DIS );
0109 
0110   /* Handle the interrupt */
0111   BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
0112 
0113   return 0;
0114 }
0115 
0116 
0117 /***********************************************************
0118  * High level IRQ handler called from shared_raw_irq_code_entry
0119  */
0120 static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
0121 {
0122   /*
0123    * Handle interrupt
0124    */
0125   switch(excNum) {
0126   case ASM_EXT_VECTOR:
0127     BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
0128     break;
0129 #if 0 /* Dealt with by C_dispatch_dec_handler(), above */
0130   case ASM_BOOKE_DEC_VECTOR:
0131     _write_BOOKE_TSR( BOOKE_TSR_DIS );
0132     BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
0133     break;
0134 #endif
0135 #if 0 /* Critical interrupts not yet supported */
0136   case ASM_BOOKE_CRIT_VECTOR:
0137     BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
0138     break;
0139 #endif
0140   }
0141 
0142   return 0;
0143 }
0144 
0145 /***********************************************************
0146  * functions to set/get/remove interrupt handlers
0147  ***********************************************************/
0148 int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
0149 {
0150   rtems_interrupt_level level;
0151 
0152   /*
0153    * check for valid irq name
0154    * if invalid, print error and return 0
0155    */
0156   if (!BSP_IS_VALID_IRQ(irq->name)) {
0157     printk("Invalid interrupt vector %d\n",irq->name);
0158     return 0;
0159   }
0160 
0161   /*
0162    * disable interrupts
0163    */
0164   rtems_interrupt_disable(level);
0165 
0166   /*
0167    * check, that default handler is installed now
0168    */
0169   if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) {
0170     rtems_interrupt_enable(level);
0171     printk("IRQ vector %d already connected\n",irq->name);
0172     return 0;
0173   }
0174 
0175   /*
0176    * store new handler data
0177    */
0178   rtemsIrqTbl[irq->name] = *irq;
0179 
0180   /*
0181    * call "on" function to enable interrupt at device
0182    */
0183   irq->on(irq);
0184 
0185   /*
0186    * reenable interrupts
0187    */
0188   rtems_interrupt_enable(level);
0189 
0190   return 1;
0191 }
0192 
0193 int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
0194 {
0195   rtems_interrupt_level level;
0196 
0197   /*
0198    * check for valid IRQ name
0199    */
0200   if (!BSP_IS_VALID_IRQ(irq->name)) {
0201     return 0;
0202   }
0203   rtems_interrupt_disable(level);
0204 
0205   /*
0206    * return current IRQ entry
0207    */
0208   *irq = rtemsIrqTbl[irq->name];
0209   rtems_interrupt_enable(level);
0210   return 1;
0211 }
0212 
0213 int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
0214 {
0215   rtems_interrupt_level level;
0216 
0217   /*
0218    * check for valid IRQ name
0219    */
0220   if (!BSP_IS_VALID_IRQ(irq->name)) {
0221     return 0;
0222   }
0223   rtems_interrupt_disable(level);
0224 
0225   /*
0226    * check, that specified handler is really connected now
0227    */
0228   if (rtemsIrqTbl[irq->name].hdl != irq->hdl) {
0229     rtems_interrupt_enable(level);
0230     return 0;
0231   }
0232 
0233   /*
0234    * disable interrupt at source
0235    */
0236   irq->off(irq);
0237 
0238   /*
0239    * restore default interrupt handler
0240    */
0241   rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry;
0242 
0243   /*
0244    * reenable interrupts
0245    */
0246   rtems_interrupt_enable(level);
0247 
0248   return 1;
0249 }
0250 
0251 /***********************************************************
0252  * functions to set/get the basic interrupt management setup
0253  ***********************************************************/
0254 /*
0255  * (Re) get info on current RTEMS interrupt management.
0256  */
0257 int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr)
0258 {
0259   *ret_ptr = BSP_rtems_irq_config;
0260   return 0;
0261 }
0262 
0263 
0264 /*
0265  * set management stuff
0266  */
0267 int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
0268 {
0269   int                    i;
0270   rtems_interrupt_level  level;
0271 
0272   rtems_interrupt_disable(level);
0273 
0274   /*
0275    * store given configuration
0276    */
0277   BSP_rtems_irq_config = config;
0278   BSP_rtems_irq_tbl    = BSP_rtems_irq_config->irqHdlTbl;
0279 
0280   /*
0281    * store any irq-like processor exceptions
0282    */
0283   for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
0284        i < BSP_PROCESSOR_IRQ_MAX_OFFSET;
0285        i++) {
0286     if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
0287       if (BSP_rtems_irq_tbl[i].on != NULL) {
0288     BSP_rtems_irq_tbl[i].on
0289       (&(BSP_rtems_irq_tbl[i]));
0290       }
0291     }
0292     else {
0293       if (BSP_rtems_irq_tbl[i].off != NULL) {
0294     BSP_rtems_irq_tbl[i].off
0295       (&(BSP_rtems_irq_tbl[i]));
0296       }
0297     }
0298   }
0299   rtems_interrupt_enable(level);
0300   return 1;
0301 }
0302 
0303 /*
0304  * dummy for an empty IRQ handler entry
0305  */
0306 static rtems_irq_connect_data emptyIrq = {
0307   0,                 /* IRQ Name                 */
0308   BSP_irq_nop_hdl,       /* handler function         */
0309   NULL,                  /* handle passed to handler */
0310   BSP_irq_nop_func,      /* on function              */
0311   BSP_irq_nop_func,      /* off function             */
0312   BSP_irq_isOn_func      /* isOn function            */
0313 };
0314 
0315 static rtems_irq_global_settings initialConfig = {
0316   BSP_IRQ_NUMBER,           /* IRQ number               */
0317   {  0,             /* IRQ Name                 */
0318      BSP_irq_nop_hdl,       /* handler function         */
0319      NULL,                  /* handle passed to handler */
0320      BSP_irq_nop_func,      /* on function              */
0321      BSP_irq_nop_func,      /* off function             */
0322      BSP_irq_isOn_func      /* isOn function            */
0323   }, /* emptyIrq */
0324   rtemsIrqTbl, /* irqHdlTbl  */
0325   0,           /* irqBase    */
0326   NULL         /* irqPrioTbl */
0327 };
0328 
0329 void BSP_rtems_irq_mngt_init(unsigned cpuId)
0330 {
0331   int i;
0332 
0333   /*
0334    * connect all exception vectors needed
0335    */
0336   ppc_exc_set_handler(ASM_EXT_VECTOR,       C_dispatch_irq_handler);
0337   ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler);
0338 
0339   /*
0340    * setup interrupt handlers table
0341    */
0342   for (i = 0;
0343        i < BSP_IRQ_NUMBER;
0344        i++) {
0345     rtemsIrqTbl[i]      = emptyIrq;
0346     rtemsIrqTbl[i].name = i;
0347   }
0348 
0349   /*
0350    * initialize interrupt management
0351    */
0352   if (!BSP_rtems_irq_mngt_set(&initialConfig)) {
0353     rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
0354   }
0355 }