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 TQM8xx BSP
0005  *
0006  * This file contains the console driver.
0007  *
0008  * Derived from: generic MPC83xx BSP
0009  */
0010 
0011 /*
0012  * Copyright (c) 2008 Thomas Doerfler, embedded brains GmbH & Co. KG
0013  * All rights reserved.
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 #include <rtems.h>
0038 #include <mpc8xx.h>
0039 
0040 #include <libcpu/powerpc-utility.h>
0041 #include <bsp/vectors.h>
0042 
0043 #include <bsp.h>
0044 #include <bsp/irq.h>
0045 #include <bsp/irq-generic.h>
0046 /*
0047  * functions to enable/disable a source at the SIU/CPM irq controller
0048  */
0049 
0050 static rtems_status_code bsp_irq_disable_at_SIU(rtems_vector_number irqnum)
0051 {
0052   rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
0053   m8xx.simask &= ~(1 << (31 - vecnum));
0054   return RTEMS_SUCCESSFUL;
0055 }
0056 
0057 static rtems_status_code bsp_irq_enable_at_SIU(rtems_vector_number irqnum)
0058 {
0059   rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
0060   m8xx.simask |= (1 << (31 - vecnum));
0061   return RTEMS_SUCCESSFUL;
0062 }
0063 
0064 static rtems_status_code bsp_irq_disable_at_CPM(rtems_vector_number irqnum)
0065 {
0066   rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
0067   m8xx.cimr &= ~(1 << (vecnum));
0068   return RTEMS_SUCCESSFUL;
0069 }
0070 
0071 static rtems_status_code bsp_irq_enable_at_CPM(rtems_vector_number irqnum)
0072 {
0073   rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
0074   m8xx.cimr |= (1 << (vecnum));
0075   return RTEMS_SUCCESSFUL;
0076 }
0077 
0078 rtems_status_code bsp_interrupt_get_attributes(
0079   rtems_vector_number         vector,
0080   rtems_interrupt_attributes *attributes
0081 )
0082 {
0083   return RTEMS_SUCCESSFUL;
0084 }
0085 
0086 rtems_status_code bsp_interrupt_is_pending(
0087   rtems_vector_number vector,
0088   bool               *pending
0089 )
0090 {
0091   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0092   bsp_interrupt_assert(pending != NULL);
0093   *pending = false;
0094   return RTEMS_UNSATISFIED;
0095 }
0096 
0097 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0098 {
0099   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0100   return RTEMS_UNSATISFIED;
0101 }
0102 
0103 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0104 {
0105   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0106   return RTEMS_UNSATISFIED;
0107 }
0108 
0109 rtems_status_code bsp_interrupt_vector_is_enabled(
0110   rtems_vector_number vector,
0111   bool               *enabled
0112 )
0113 {
0114   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0115   bsp_interrupt_assert(enabled != NULL);
0116   *enabled = false;
0117   return RTEMS_UNSATISFIED;
0118 }
0119 
0120 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0121 {
0122   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0123 
0124   if (BSP_IS_CPM_IRQ(vector)) {
0125     bsp_irq_enable_at_CPM(vector);
0126   } else if (BSP_IS_SIU_IRQ(vector)) {
0127     bsp_irq_enable_at_SIU(vector);
0128   }
0129 
0130   return RTEMS_SUCCESSFUL;
0131 }
0132 
0133 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0134 {
0135   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0136 
0137   if (BSP_IS_CPM_IRQ(vector)) {
0138     bsp_irq_disable_at_CPM(vector);
0139   } else if (BSP_IS_SIU_IRQ(vector)) {
0140     bsp_irq_disable_at_SIU(vector);
0141   }
0142 
0143   return RTEMS_SUCCESSFUL;
0144 }
0145 
0146 rtems_status_code bsp_interrupt_set_priority(
0147   rtems_vector_number vector,
0148   uint32_t priority
0149 )
0150 {
0151   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0152   return RTEMS_UNSATISFIED;
0153 }
0154 
0155 rtems_status_code bsp_interrupt_get_priority(
0156   rtems_vector_number vector,
0157   uint32_t *priority
0158 )
0159 {
0160   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0161   bsp_interrupt_assert(priority != NULL);
0162   return RTEMS_UNSATISFIED;
0163 }
0164 
0165 /*
0166  *  IRQ Handler: this is called from the primary exception dispatcher
0167  */
0168 static int BSP_irq_handle_at_cpm(void)
0169 {
0170   int32_t  cpvecnum;
0171   uint32_t msr;
0172 
0173   /* Get vector number: write IACK=1, then read vectir */
0174   m8xx.civr = 1;
0175   cpvecnum  = (m8xx.civr >> 11) + BSP_CPM_IRQ_LOWEST_OFFSET;
0176 
0177   /*
0178    * Check the vector number,
0179    * enable exceptions and dispatch the handler.
0180    * NOTE: lower-prio interrupts are automatically masked in CPIC
0181    */
0182   if (BSP_IS_CPM_IRQ(cpvecnum)) {
0183     /* Enable all interrupts */
0184     msr = ppc_external_exceptions_enable();
0185     /* Dispatch interrupt handlers */
0186     bsp_interrupt_handler_dispatch(cpvecnum);
0187     /* Restore machine state */
0188     ppc_external_exceptions_disable(msr);
0189   }
0190   else {
0191     /* not valid vector */
0192     bsp_interrupt_handler_default(cpvecnum);
0193   }
0194   /*
0195    * clear "in-service" bit
0196    */
0197   m8xx.cisr = 1 << (cpvecnum - BSP_CPM_IRQ_LOWEST_OFFSET);
0198 
0199   return 0;
0200 }
0201 
0202 static int BSP_irq_handle_at_siu( unsigned excNum)
0203 {
0204   int32_t  sivecnum;
0205   uint32_t msr;
0206   bool  is_cpm_irq;
0207   uint32_t simask_save;
0208   /*
0209    * check, if interrupt is pending
0210    * and repeat as long as valid interrupts are pending
0211    */
0212   while (0 != (m8xx.simask & m8xx.sipend)) {
0213     /* Get vector number */
0214     sivecnum     = (m8xx.sivec >> 26);
0215     is_cpm_irq = (sivecnum == BSP_CPM_INTERRUPT);
0216     /*
0217      * Check the vector number, mask lower priority interrupts, enable
0218      * exceptions and dispatch the handler.
0219      */
0220     if (BSP_IS_SIU_IRQ(sivecnum)) {
0221       simask_save = m8xx.simask;
0222       /*
0223        * if this is the CPM interrupt, mask lower prio interrupts at SIU
0224        * else mask lower and same priority interrupts
0225        */
0226       m8xx.simask &= ~0 << (32
0227                 - sivecnum
0228                 - ((is_cpm_irq) ? 1 : 0));
0229 
0230       if (is_cpm_irq) {
0231     BSP_irq_handle_at_cpm();
0232       }
0233       else {
0234     /* Enable all interrupts */
0235     msr = ppc_external_exceptions_enable();
0236     /* Dispatch interrupt handlers */
0237     bsp_interrupt_handler_dispatch(sivecnum + BSP_SIU_IRQ_LOWEST_OFFSET);
0238     /* Restore machine state */
0239     ppc_external_exceptions_disable(msr);
0240     /*
0241      * clear pending bit, if edge triggered interrupt input
0242      */
0243     m8xx.sipend = 1 << (31 - sivecnum);
0244       }
0245 
0246 
0247       /* Restore initial masks */
0248       m8xx.simask = simask_save;
0249     } else {
0250       /* not valid vector */
0251       bsp_interrupt_handler_default(sivecnum);
0252     }
0253   }
0254   return 0;
0255 }
0256 
0257 /*
0258  * Activate the CPIC
0259  */
0260 static void mpc8xx_cpic_initialize( void)
0261 {
0262   rtems_status_code sc;
0263 
0264   /*
0265    * mask off all interrupts
0266    */
0267   m8xx.cimr   = 0;
0268   /*
0269    * make sure CPIC request proper level at SIU interrupt controller
0270    */
0271   m8xx.cicr  = (0x00e41f80 |
0272         ((BSP_CPM_INTERRUPT/2) << 13));
0273   /*
0274    * enable CPIC interrupt in SIU interrupt controller
0275    */
0276   sc = bsp_irq_enable_at_SIU(BSP_CPM_INTERRUPT);
0277   _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL);
0278 }
0279 
0280 /*
0281  * Activate the SIU interrupt controller
0282  */
0283 static void mpc8xx_siu_int_initialize( void)
0284 {
0285   /*
0286    * mask off all interrupts
0287    */
0288   m8xx.simask = 0;
0289 }
0290 
0291 static int mpc8xx_exception_handler(BSP_Exception_frame *frame,
0292                  unsigned exception_number)
0293 {
0294   return BSP_irq_handle_at_siu(exception_number);
0295 }
0296 
0297 void bsp_interrupt_facility_initialize()
0298 {
0299   rtems_status_code sc;
0300 
0301   /* Install exception handler */
0302   sc = ppc_exc_set_handler(ASM_EXT_VECTOR, mpc8xx_exception_handler);
0303   _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL);
0304 
0305   /* Initialize the SIU interrupt controller */
0306   mpc8xx_siu_int_initialize();
0307 
0308   /* Initialize the CPIC interrupt controller */
0309   mpc8xx_cpic_initialize();
0310 }