Back to home page

LXR

 
 

    


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

0001 /* irq_init.c
0002  *
0003  *  This file contains the implementation of rtems initialization
0004  *  related to interrupt handling.
0005  *
0006  *  CopyRight (C) 1999 valette@crf.canon.fr
0007  *
0008  * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
0009  * to make it valid for MVME2300 Motorola boards.
0010  *
0011  * Till Straumann <strauman@slac.stanford.edu>, 12/20/2001:
0012  * Use the new interface to openpic_init
0013  *
0014  *  The license and distribution terms for this file may be
0015  *  found in the file LICENSE in this distribution or at
0016  *  http://www.rtems.org/license/LICENSE.
0017  */
0018 
0019 #include <libcpu/io.h>
0020 #include <libcpu/spr.h>
0021 #include <bsp/pci.h>
0022 #include <bsp/residual.h>
0023 #include <bsp/irq.h>
0024 #if BSP_PCI_IRQ_NUMBER > 0
0025 #include <bsp/openpic.h>
0026 #endif
0027 #include <bsp/irq_supp.h>
0028 #include <bsp.h>
0029 #include <bsp/motorola.h>
0030 #include <rtems/bspIo.h>
0031 
0032 typedef struct {
0033   unsigned char bus;    /* few chance the PCI/ISA bridge is not on first bus but ... */
0034   unsigned char device;
0035   unsigned char function;
0036 } pci_isa_bridge_device;
0037 
0038 pci_isa_bridge_device* via_82c586 = 0;
0039 #ifndef qemu
0040 static pci_isa_bridge_device bridge;
0041 #endif
0042 
0043 /*
0044  * default methods
0045  */
0046 static void nop_hdl(rtems_irq_hdl_param ignored)
0047 {
0048 }
0049 
0050 static void nop_irq_enable(const struct __rtems_irq_connect_data__*ignored)
0051 {
0052 }
0053 
0054 static int irq_is_connected(const struct __rtems_irq_connect_data__*ignored)
0055 {
0056   return 0;
0057 }
0058 
0059 
0060 static rtems_irq_connect_data       rtemsIrq[BSP_IRQ_NUMBER];
0061 static rtems_irq_global_settings        initial_config;
0062 static rtems_irq_connect_data       defaultIrq = {
0063   0,                /* vector */
0064   nop_hdl,          /* hdl */
0065   NULL,             /* handle */
0066   nop_irq_enable,   /* on */
0067   nop_irq_enable,   /* off */
0068   irq_is_connected  /* isOn */
0069 #ifdef BSP_SHARED_HANDLER_SUPPORT
0070   , NULL /* next_handler */
0071 #endif
0072 };
0073 static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
0074   /*
0075    * actual priorities for interrupt :
0076    *    0   means that only current interrupt is masked
0077    *    255 means all other interrupts are masked
0078    */
0079   /*
0080    * ISA interrupts.
0081    * The second entry has a priority of 255 because
0082    * it is the slave pic entry and should always remain
0083    * unmasked.
0084    */
0085   0,0,
0086   255,
0087   0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0088 #if BSP_PCI_IRQ_NUMBER > 0
0089   /*
0090    * PCI Interrupts
0091    */
0092   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
0093 #endif
0094   /*
0095    * Processor exceptions handled as interrupts
0096    */
0097   0
0098 };
0099 
0100 #if BSP_PCI_IRQ_NUMBER > 0
0101 #if defined(mot_ppc_mvme2100)
0102 static unsigned char mvme2100_openpic_initpolarities[16] = {
0103     0,  /* Not used - should be disabled */
0104     0,  /* DEC21143 Controller */
0105     0,  /* PMC/PC-MIP Type I Slot 0 */
0106     0,  /* PC-MIP Type I Slot 1 */
0107     0,  /* PC-MIP Type II Slot 0 */
0108     0,  /* PC-MIP Type II Slot 1 */
0109     0,  /* Not used - should be disabled */
0110     0,  /* PCI Expansion Interrupt A/Universe II (LINT0) */
0111     0,  /* PCI Expansion Interrupt B/Universe II (LINT1) */
0112     0,  /* PCI Expansion Interrupt C/Universe II (LINT2) */
0113     0,  /* PCI Expansion Interrupt D/Universe II (LINT3) */
0114     0,  /* Not used - should be disabled */
0115     0,  /* Not used - should be disabled */
0116     1,  /* 16550 UART */
0117     0,  /* Front panel Abort Switch */
0118     0,  /* RTC IRQ */
0119 };
0120 
0121 static unsigned char mvme2100_openpic_initsenses[] = {
0122     0,  /* Not used - should be disabled */
0123     1,  /* DEC21143 Controller */
0124     1,  /* PMC/PC-MIP Type I Slot 0 */
0125     1,  /* PC-MIP Type I Slot 1 */
0126     1,  /* PC-MIP Type II Slot 0 */
0127     1,  /* PC-MIP Type II Slot 1 */
0128     0,  /* Not used - should be disabled */
0129     1,  /* PCI Expansion Interrupt A/Universe II (LINT0) */
0130     1,  /* PCI Expansion Interrupt B/Universe II (LINT1) */
0131     1,  /* PCI Expansion Interrupt C/Universe II (LINT2) */
0132     1,  /* PCI Expansion Interrupt D/Universe II (LINT3) */
0133     0,  /* Not used - should be disabled */
0134     0,  /* Not used - should be disabled */
0135     1,  /* 16550 UART */
0136     0,  /* Front panel Abort Switch */
0137     1,  /* RTC IRQ */
0138 };
0139 #else
0140 static unsigned char mcp750_openpic_initpolarities[16] = {
0141     1,  /* 8259 cascade */
0142     0,  /* all the rest of them */
0143 };
0144 
0145 static unsigned char mcp750_openpic_initsenses[] = {
0146     1,  /* MCP750_INT_PCB(8259) */
0147     0,  /* MCP750_INT_FALCON_ECC_ERR */
0148     1,  /* MCP750_INT_PCI_ETHERNET */
0149     1,  /* MCP750_INT_PCI_PMC */
0150     1,  /* MCP750_INT_PCI_WATCHDOG_TIMER1 */
0151     1,  /* MCP750_INT_PCI_PRST_SIGNAL */
0152     1,  /* MCP750_INT_PCI_FALL_SIGNAL */
0153     1,  /* MCP750_INT_PCI_DEG_SIGNAL */
0154     1,  /* MCP750_INT_PCI_BUS1_INTA */
0155     1,  /* MCP750_INT_PCI_BUS1_INTB */
0156     1,  /* MCP750_INT_PCI_BUS1_INTC */
0157     1,  /* MCP750_INT_PCI_BUS1_INTD */
0158     1,  /* MCP750_INT_PCI_BUS2_INTA */
0159     1,  /* MCP750_INT_PCI_BUS2_INTB */
0160     1,  /* MCP750_INT_PCI_BUS2_INTC */
0161     1,  /* MCP750_INT_PCI_BUS2_INTD */
0162 };
0163 #endif
0164 #endif
0165 
0166 #if BSP_ISA_IRQ_NUMBER > 0 && !defined(qemu)
0167 void VIA_isa_bridge_interrupts_setup(void)
0168 {
0169   pci_isa_bridge_device pci_dev;
0170   uint32_t temp;
0171   unsigned char tmp;
0172   unsigned char maxBus;
0173   unsigned found = 0;
0174 
0175   maxBus = pci_bus_count();
0176   pci_dev.function  = 0; /* Assumes the bidge is the first function */
0177 
0178   for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
0179 #ifdef SCAN_PCI_PRINT
0180     printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
0181 #endif
0182     for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
0183 #ifdef SCAN_PCI_PRINT
0184       printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
0185 #endif
0186       pci_read_config_dword(pci_dev.bus, pci_dev.device,  pci_dev.function,
0187                    PCI_VENDOR_ID, &temp);
0188 #ifdef SCAN_PCI_PRINT
0189       printk("Vendor/device = %x\n", temp);
0190 #endif
0191       if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
0192      ) {
0193     bridge = pci_dev;
0194     via_82c586 = &bridge;
0195 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0196     /*
0197      * Should print : bus = 0, device = 11, function = 0 on a MCP750.
0198      */
0199     printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
0200            via_82c586->bus,
0201            via_82c586->device,
0202            via_82c586->function);
0203 #endif
0204     found = 1;
0205     goto loop_exit;
0206 
0207       }
0208     }
0209   }
0210 loop_exit:
0211   if (!found) rtems_panic("VIA_82C586 PCI/ISA bridge not found!n");
0212 
0213   tmp = inb(0x810);
0214   if  ( !(tmp & 0x2)) {
0215 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0216     printk("This is a second generation MCP750 board\n");
0217     printk("We must reprogram the PCI/ISA bridge...\n");
0218 #endif
0219     pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0220              0x47,  &tmp);
0221 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0222     printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
0223 #endif
0224     /*
0225      * Enable 4D0/4D1 ISA interrupt level/edge config registers
0226      */
0227     tmp |= 0x20;
0228     pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0229               0x47, tmp);
0230     /*
0231      * Now program the ISA interrupt edge/level
0232      */
0233     tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
0234     outb(tmp, ISA8259_S_ELCR);
0235     tmp = ELCRM_INT5_LVL;
0236     outb(tmp, ISA8259_M_ELCR);
0237     /*
0238      * Set the Interrupt inputs to non-inverting level interrupt
0239      */
0240     pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0241                 0x54, &tmp);
0242 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0243     printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
0244 #endif
0245     tmp = 0;
0246     pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0247               0x54, tmp);
0248   }
0249   else {
0250 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0251     printk("This is a first generation MCP750 board\n");
0252     printk("We just show the actual value used by PCI/ISA bridge\n");
0253 #endif
0254     pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0255              0x47,  &tmp);
0256 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0257     printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
0258 #endif
0259     /*
0260      * Show the Interrupt inputs inverting/non-inverting level status
0261      */
0262     pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
0263              0x54, &tmp);
0264 #ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
0265     printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
0266 #endif
0267   }
0268 }
0269 #endif
0270 
0271   /*
0272    * This code assumes the exceptions management setup has already
0273    * been done. We just need to replace the exceptions that will
0274    * be handled like interrupt. On mcp750/mpc750 and many PPC processors
0275    * this means the decrementer exception and the external exception.
0276    */
0277 void BSP_rtems_irq_mng_init(unsigned cpuId)
0278 {
0279 #if BSP_ISA_IRQ_NUMBER > 0 && !defined(mot_ppc_mvme2100)
0280   int known_cpi_isa_bridge = 0;
0281 #endif
0282   int i;
0283   int r;
0284 
0285   /*
0286    * First initialize the Interrupt management hardware
0287    */
0288 #if defined(mot_ppc_mvme2100)
0289 #ifdef TRACE_IRQ_INIT
0290   printk("Going to initialize EPIC interrupt controller (openpic compliant)\n");
0291 #endif
0292   /* EPIC sources don't start at the regular place; define appropriate offset
0293    * prior to initializing the PIC.
0294    */
0295   openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses, 16, 16, BSP_bus_frequency);
0296 #else
0297 #if BSP_PCI_IRQ_NUMBER > 0
0298 #ifdef TRACE_IRQ_INIT
0299   printk("Going to initialize raven interrupt controller (openpic compliant)\n");
0300 #endif
0301   openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses, 0, 0, 0);
0302 #ifdef TRACE_IRQ_INIT
0303   printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n");
0304 #endif
0305 #endif
0306 
0307 #if BSP_ISA_IRQ_NUMBER > 0
0308   if ( currentBoard == MESQUITE ) {
0309 #ifndef qemu
0310     VIA_isa_bridge_interrupts_setup();
0311 #endif
0312     known_cpi_isa_bridge = 1;
0313   }
0314   if ( currentBoard == MVME_2300 || currentBoard == MVME_2600_2700_W_MVME761 ) {
0315     /* nothing to do for W83C553 bridge */
0316     known_cpi_isa_bridge = 1;
0317   }
0318   if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) {
0319      /* W83C554, don't to anything at the moment.  gregm 11/6/2002 */
0320      known_cpi_isa_bridge = 1;
0321   }
0322 
0323   if (!known_cpi_isa_bridge) {
0324     printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n");
0325     printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n");
0326     printk("currentBoard = %i\n", currentBoard);
0327   }
0328 #ifdef TRACE_IRQ_INIT
0329   printk("Going to initialize the ISA PC legacy IRQ management hardware\n");
0330 #endif
0331   BSP_i8259s_init();
0332 #endif
0333 
0334 #endif
0335 
0336   /*
0337    * Initialize RTEMS management interrupt table
0338    */
0339     /*
0340      * re-init the rtemsIrq table
0341      */
0342     for (i = 0; i < BSP_IRQ_NUMBER; i++) {
0343       rtemsIrq[i]      = defaultIrq;
0344       rtemsIrq[i].name = i;
0345     }
0346     /*
0347      * Init initial Interrupt management config
0348      */
0349     initial_config.irqNb    = BSP_IRQ_NUMBER;
0350     initial_config.defaultEntry = defaultIrq;
0351     initial_config.irqHdlTbl    = rtemsIrq;
0352     initial_config.irqBase  = BSP_LOWEST_OFFSET;
0353     initial_config.irqPrioTbl   = irqPrioTable;
0354 
0355 #ifdef BSP_POWERPC_IRQ_GENERIC_SUPPORT
0356 #ifdef TRACE_IRQ_INIT
0357     printk("RTEMS IRQ management: irq-generic\n");
0358 #endif
0359     r = BSP_rtems_irq_generic_set(&initial_config);
0360 #else
0361 #ifdef TRACE_IRQ_INIT
0362     printk("RTEMS IRQ management: legacy\n");
0363 #endif
0364     r = BSP_rtems_irq_mngt_set(&initial_config);
0365 #endif
0366 
0367     if (!r) {
0368       /*
0369        * put something here that will show the failure...
0370        */
0371       rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
0372     }
0373 
0374 #ifdef TRACE_IRQ_INIT
0375     printk("RTEMS IRQ management is now operational\n");
0376 #endif
0377 }