source: rtems/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c @ eba2e4f

4.104.114.84.95
Last change on this file since eba2e4f was 338f1dc, checked in by Joel Sherrill <joel.sherrill@…>, on 01/10/00 at 13:26:00

Patch from Eric Valette <valette@…> that makes sure the
interrupt code works on "old buggy MCP750 boards". The symptom was
that there was no ethernet PCI IRQ at all.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/* irq_init.c
2 *
3 *  This file contains the implementation of rtems initialization
4 *  related to interrupt handling.
5 *
6 *  CopyRight (C) 1999 valette@crf.canon.fr
7 *
8 * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
9 * to make it valid for MVME2300 Motorola boards.
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 *  $Id$
16 */
17#include <bsp/consoleIo.h>
18#include <libcpu/io.h>
19#include <libcpu/spr.h>
20#include <bsp/pci.h>
21#include <bsp/residual.h>
22#include <bsp/openpic.h>
23#include <bsp/irq.h>
24#include <bsp.h>
25#include <libcpu/raw_exception.h>
26#include <bsp/motorola.h>
27
28/*
29#define SHOW_ISA_PCI_BRIDGE_SETTINGS
30*/
31
32typedef struct {
33  unsigned char bus;    /* few chance the PCI/ISA bridge is not on first bus but ... */
34  unsigned char device;
35  unsigned char function;
36} pci_isa_bridge_device;
37
38pci_isa_bridge_device* via_82c586 = 0;
39static pci_isa_bridge_device bridge;
40
41extern unsigned int external_exception_vector_prolog_code_size;
42extern void external_exception_vector_prolog_code();
43extern unsigned int decrementer_exception_vector_prolog_code_size;
44extern void decrementer_exception_vector_prolog_code();
45
46/*
47 * default on/off function
48 */
49static void nop_func(){}
50/*
51 * default isOn function
52 */
53static int not_connected() {return 0;}
54/*
55 * default possible isOn function
56 */
57static int connected() {return 1;}
58
59static rtems_irq_connect_data           rtemsIrq[BSP_IRQ_NUMBER];
60static rtems_irq_global_settings        initial_config;
61static rtems_irq_connect_data           defaultIrq = {
62  /* vectorIdex,         hdl            , on            , off           , isOn */
63  0,                     nop_func       , nop_func      , nop_func      , not_connected
64};
65static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
66  /*
67   * actual rpiorities for interrupt :
68   *    0   means that only current interrupt is masked
69   *    255 means all other interrupts are masked
70   */
71  /*
72   * ISA interrupts.
73   * The second entry has a priority of 255 because
74   * it is the slave pic entry and is should always remain
75   * unmasked.
76   */
77  0,0,
78  255,
79  0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
80  /*
81   * PCI Interrupts
82   */
83  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* for raven prio 0 means unactive... */
84  /*
85   * Processor exceptions handled as interrupts
86   */
87  0
88};
89
90static unsigned char mcp750_openpic_initsenses[] = {
91    1,  /* MCP750_INT_PCB(8259) */
92    0,  /* MCP750_INT_FALCON_ECC_ERR */
93    1,  /* MCP750_INT_PCI_ETHERNET */
94    1,  /* MCP750_INT_PCI_PMC */
95    1,  /* MCP750_INT_PCI_WATCHDOG_TIMER1 */
96    1,  /* MCP750_INT_PCI_PRST_SIGNAL */
97    1,  /* MCP750_INT_PCI_FALL_SIGNAL */
98    1,  /* MCP750_INT_PCI_DEG_SIGNAL */
99    1,  /* MCP750_INT_PCI_BUS1_INTA */
100    1,  /* MCP750_INT_PCI_BUS1_INTB */
101    1,  /* MCP750_INT_PCI_BUS1_INTC */
102    1,  /* MCP750_INT_PCI_BUS1_INTD */
103    1,  /* MCP750_INT_PCI_BUS2_INTA */
104    1,  /* MCP750_INT_PCI_BUS2_INTB */
105    1,  /* MCP750_INT_PCI_BUS2_INTC */
106    1,  /* MCP750_INT_PCI_BUS2_INTD */
107};
108
109void VIA_isa_bridge_interrupts_setup(void)
110{
111  pci_isa_bridge_device pci_dev;
112  unsigned int temp;
113  unsigned char tmp;
114  unsigned char maxBus;
115  unsigned found = 0;
116
117  maxBus = BusCountPCI();
118  pci_dev.function      = 0; /* Assumes the bidge is the first function */
119     
120  for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
121#ifdef SCAN_PCI_PRINT       
122    printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
123#endif       
124    for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
125#ifdef SCAN_PCI_PRINT       
126      printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
127#endif       
128      pci_read_config_dword(pci_dev.bus, pci_dev.device,  pci_dev.function,
129                               PCI_VENDOR_ID, &temp);
130#ifdef SCAN_PCI_PRINT       
131      printk("Vendor/device = %x\n", temp);
132#endif
133      if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
134         ) {
135        bridge = pci_dev;
136        via_82c586 = &bridge;
137#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
138        /*
139         * Should print : bus = 0, device = 11, function = 0 on a MCP750.
140         */
141        printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
142               via_82c586->bus,
143               via_82c586->device,
144               via_82c586->function);
145#endif       
146        found = 1;
147        goto loop_exit;
148           
149      }
150    }
151  }
152loop_exit:
153  if (!found) BSP_panic("VIA_82C586 PCI/ISA bridge not found!n");
154     
155  tmp = inb(0x810);
156  if  ( !(tmp & 0x2)) {
157#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
158    printk("This is a second generation MCP750 board\n");
159    printk("We must reprogram the PCI/ISA bridge...\n");
160#endif       
161    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
162                         0x47,  &tmp);
163#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
164    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
165#endif       
166    /*
167     * Enable 4D0/4D1 ISA interrupt level/edge config registers
168     */
169    tmp |= 0x20;
170    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
171                          0x47, tmp);
172    /*
173     * Now program the ISA interrupt edge/level
174     */
175    tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
176    outb(tmp, ISA8259_S_ELCR);
177    tmp = ELCRM_INT5_LVL;
178    outb(tmp, ISA8259_M_ELCR);;
179    /*
180     * Set the Interrupt inputs to non-inverting level interrupt
181     */
182    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
183                            0x54, &tmp);
184#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
185    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
186#endif       
187    tmp = 0;
188    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
189                          0x54, tmp);
190  }
191  else {
192#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
193    printk("This is a first generation MCP750 board\n");
194    printk("We just show the actual value used by PCI/ISA bridge\n");
195#endif       
196    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
197                         0x47,  &tmp);
198#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
199    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
200#endif       
201    /*
202     * Show the Interrupt inputs inverting/non-inverting level status
203     */
204    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
205                         0x54, &tmp);
206#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS     
207    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
208#endif       
209  }
210}
211
212  /*
213   * This code assumes the exceptions management setup has already
214   * been done. We just need to replace the exceptions that will
215   * be handled like interrupt. On mcp750/mpc750 and many PPC processors
216   * this means the decrementer exception and the external exception.
217   */
218void BSP_rtems_irq_mng_init(unsigned cpuId)
219{
220  rtems_raw_except_connect_data vectorDesc;
221  int known_cpi_isa_bridge = 0;
222  int i;
223 
224  /*
225   * First initialize the Interrupt management hardware
226   */
227  OpenPIC_InitSenses = mcp750_openpic_initsenses;
228  OpenPIC_NumInitSenses = sizeof(mcp750_openpic_initsenses) / sizeof(char);
229#ifdef TRACE_IRQ_INIT 
230  printk("Going to initialize raven interrupt controller (openpic compliant)\n");
231#endif       
232  openpic_init(1);
233#ifdef TRACE_IRQ_INIT 
234  printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n");
235#endif
236  if ( currentBoard == MESQUITE ) {
237    VIA_isa_bridge_interrupts_setup();
238    known_cpi_isa_bridge = 1;
239  }
240  if ( currentBoard == MVME_2300 ) {
241    /* nothing to do for W83C553 bridge */
242    known_cpi_isa_bridge = 1;
243  }
244  if (!known_cpi_isa_bridge) {
245    printk("Please add code for PCI/ISA bridge init to libbsp/shared/irq/irq_init.c\n");
246    printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n");
247  }
248#ifdef TRACE_IRQ_INIT 
249  printk("Going to initialize the ISA PC legacy IRQ management hardware\n");
250#endif       
251  BSP_i8259s_init();
252  /*
253   * Initialize Rtems management interrupt table
254   */
255    /*
256     * re-init the rtemsIrq table
257     */
258    for (i = 0; i < BSP_IRQ_NUMBER; i++) {
259      rtemsIrq[i]      = defaultIrq;
260      rtemsIrq[i].name = i;
261    }
262    /*
263     * Init initial Interrupt management config
264     */
265    initial_config.irqNb        = BSP_IRQ_NUMBER;
266    initial_config.defaultEntry = defaultIrq;
267    initial_config.irqHdlTbl    = rtemsIrq;
268    initial_config.irqBase      = BSP_ASM_IRQ_VECTOR_BASE;
269    initial_config.irqPrioTbl   = irqPrioTable;
270
271    if (!BSP_rtems_irq_mngt_set(&initial_config)) {
272      /*
273       * put something here that will show the failure...
274       */
275      BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
276    }
277 
278  /*
279   * We must connect the raw irq handler for the two
280   * expected interrupt sources : decrementer and external interrupts.
281   */
282    vectorDesc.exceptIndex      =       ASM_DEC_VECTOR;
283    vectorDesc.hdl.vector       =       ASM_DEC_VECTOR;
284    vectorDesc.hdl.raw_hdl      =       decrementer_exception_vector_prolog_code;
285    vectorDesc.hdl.raw_hdl_size =       (unsigned) &decrementer_exception_vector_prolog_code_size;
286    vectorDesc.on               =       nop_func;
287    vectorDesc.off              =       nop_func;
288    vectorDesc.isOn             =       connected;
289    if (!mpc60x_set_exception (&vectorDesc)) {
290      BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
291    }
292    vectorDesc.exceptIndex      =       ASM_EXT_VECTOR;
293    vectorDesc.hdl.vector       =       ASM_EXT_VECTOR;
294    vectorDesc.hdl.raw_hdl      =       external_exception_vector_prolog_code;
295    vectorDesc.hdl.raw_hdl_size =       (unsigned) &external_exception_vector_prolog_code_size;
296    if (!mpc60x_set_exception (&vectorDesc)) {
297      BSP_panic("Unable to initialize RTEMS external raw exception\n");
298    }
299#ifdef TRACE_IRQ_INIT 
300    printk("RTEMS IRQ management is now operationnal\n");
301#endif
302}
303
Note: See TracBrowser for help on using the repository browser.