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

4.104.114.84.95
Last change on this file since 0ed348f was 0ed348f, checked in by Till Straumann <strauman@…>, on 12/02/05 at 20:45:57

2005-12-02 Till Straumann <strauman@…>

  • shared/irq/irq_init.c, shared/openpic/openpic.h shared/openpic/openpic.c: The 8240's EPIC has a 'serial' mode of operation for multiplexing 16 interrupt lines. This introduces a pipeline delay which can cause spurious interrupts unless ending the interrupt cycle (EOI) is delayed accordingly.
  • Property mode set to 100644
File size: 11.7 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 * Till Straumann <strauman@slac.stanford.edu>, 12/20/2001:
12 * Use the new interface to openpic_init
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.com/license/LICENSE.
17 *
18 *  $Id$
19 */
20
21#include <libcpu/io.h>
22#include <libcpu/spr.h>
23#include <bsp/pci.h>
24#include <bsp/residual.h>
25#include <bsp/openpic.h>
26#include <bsp/irq.h>
27#include <bsp.h>
28#include <libcpu/raw_exception.h>
29#include <bsp/motorola.h>
30#include <rtems/bspIo.h>
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
41/*
42 * default on/off function
43 */
44static void nop_func(){}
45/*
46 * default isOn function
47 */
48static int not_connected() {return 0;}
49/*
50 * default possible isOn function
51static int connected() {return 1;}
52 */
53
54static rtems_irq_connect_data           rtemsIrq[BSP_IRQ_NUMBER];
55static rtems_irq_global_settings        initial_config;
56static rtems_irq_connect_data           defaultIrq = {
57  /* vectorIdex,         hdl            , handle        , on            , off           , isOn */
58  0,                     nop_func       , NULL          , nop_func      , nop_func      , not_connected
59};
60static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
61  /*
62   * actual priorities for interrupt :
63   *    0   means that only current interrupt is masked
64   *    255 means all other interrupts are masked
65   */
66  /*
67   * ISA interrupts.
68   * The second entry has a priority of 255 because
69   * it is the slave pic entry and should always remain
70   * unmasked.
71   */
72  0,0,
73  255,
74  0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
75  /*
76   * PCI Interrupts
77   */
78  8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
79  /*
80   * Processor exceptions handled as interrupts
81   */
82  0
83};
84
85#if defined(mvme2100)
86static unsigned char mvme2100_openpic_initpolarities[16] = {
87    0,  /* Not used - should be disabled */
88    0,  /* DEC21143 Controller */
89    0,  /* PMC/PC-MIP Type I Slot 0 */
90    0,  /* PC-MIP Type I Slot 1 */
91    0,  /* PC-MIP Type II Slot 0 */
92    0,  /* PC-MIP Type II Slot 1 */
93    0,  /* Not used - should be disabled */
94    0,  /* PCI Expansion Interrupt A/Universe II (LINT0) */
95    0,  /* PCI Expansion Interrupt B/Universe II (LINT1) */
96    0,  /* PCI Expansion Interrupt C/Universe II (LINT2) */
97    0,  /* PCI Expansion Interrupt D/Universe II (LINT3) */
98    0,  /* Not used - should be disabled */
99    0,  /* Not used - should be disabled */
100    1,  /* 16550 UART */
101    0,  /* Front panel Abort Switch */
102    0,  /* RTC IRQ */
103};
104
105static unsigned char mvme2100_openpic_initsenses[] = {
106    0,  /* Not used - should be disabled */
107    1,  /* DEC21143 Controller */
108    1,  /* PMC/PC-MIP Type I Slot 0 */
109    1,  /* PC-MIP Type I Slot 1 */
110    1,  /* PC-MIP Type II Slot 0 */
111    1,  /* PC-MIP Type II Slot 1 */
112    0,  /* Not used - should be disabled */
113    1,  /* PCI Expansion Interrupt A/Universe II (LINT0) */
114    1,  /* PCI Expansion Interrupt B/Universe II (LINT1) */
115    1,  /* PCI Expansion Interrupt C/Universe II (LINT2) */
116    1,  /* PCI Expansion Interrupt D/Universe II (LINT3) */
117    0,  /* Not used - should be disabled */
118    0,  /* Not used - should be disabled */
119    1,  /* 16550 UART */
120    0,  /* Front panel Abort Switch */
121    1,  /* RTC IRQ */
122};
123#else
124static unsigned char mcp750_openpic_initpolarities[16] = {
125    1,  /* 8259 cascade */
126    0,  /* all the rest of them */
127};
128
129static unsigned char mcp750_openpic_initsenses[] = {
130    1,  /* MCP750_INT_PCB(8259) */
131    0,  /* MCP750_INT_FALCON_ECC_ERR */
132    1,  /* MCP750_INT_PCI_ETHERNET */
133    1,  /* MCP750_INT_PCI_PMC */
134    1,  /* MCP750_INT_PCI_WATCHDOG_TIMER1 */
135    1,  /* MCP750_INT_PCI_PRST_SIGNAL */
136    1,  /* MCP750_INT_PCI_FALL_SIGNAL */
137    1,  /* MCP750_INT_PCI_DEG_SIGNAL */
138    1,  /* MCP750_INT_PCI_BUS1_INTA */
139    1,  /* MCP750_INT_PCI_BUS1_INTB */
140    1,  /* MCP750_INT_PCI_BUS1_INTC */
141    1,  /* MCP750_INT_PCI_BUS1_INTD */
142    1,  /* MCP750_INT_PCI_BUS2_INTA */
143    1,  /* MCP750_INT_PCI_BUS2_INTB */
144    1,  /* MCP750_INT_PCI_BUS2_INTC */
145    1,  /* MCP750_INT_PCI_BUS2_INTD */
146};
147#endif
148
149void VIA_isa_bridge_interrupts_setup(void)
150{
151  pci_isa_bridge_device pci_dev;
152  unsigned int temp;
153  unsigned char tmp;
154  unsigned char maxBus;
155  unsigned found = 0;
156
157  maxBus = pci_bus_count();
158  pci_dev.function      = 0; /* Assumes the bidge is the first function */
159
160  for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
161#ifdef SCAN_PCI_PRINT
162    printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
163#endif
164    for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
165#ifdef SCAN_PCI_PRINT
166      printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
167#endif
168      pci_read_config_dword(pci_dev.bus, pci_dev.device,  pci_dev.function,
169                               PCI_VENDOR_ID, &temp);
170#ifdef SCAN_PCI_PRINT
171      printk("Vendor/device = %x\n", temp);
172#endif
173      if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
174         ) {
175        bridge = pci_dev;
176        via_82c586 = &bridge;
177#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
178        /*
179         * Should print : bus = 0, device = 11, function = 0 on a MCP750.
180         */
181        printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
182               via_82c586->bus,
183               via_82c586->device,
184               via_82c586->function);
185#endif
186        found = 1;
187        goto loop_exit;
188
189      }
190    }
191  }
192loop_exit:
193  if (!found) BSP_panic("VIA_82C586 PCI/ISA bridge not found!n");
194
195  tmp = inb(0x810);
196  if  ( !(tmp & 0x2)) {
197#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
198    printk("This is a second generation MCP750 board\n");
199    printk("We must reprogram the PCI/ISA bridge...\n");
200#endif
201    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
202                         0x47,  &tmp);
203#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
204    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
205#endif
206    /*
207     * Enable 4D0/4D1 ISA interrupt level/edge config registers
208     */
209    tmp |= 0x20;
210    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
211                          0x47, tmp);
212    /*
213     * Now program the ISA interrupt edge/level
214     */
215    tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
216    outb(tmp, ISA8259_S_ELCR);
217    tmp = ELCRM_INT5_LVL;
218    outb(tmp, ISA8259_M_ELCR);;
219    /*
220     * Set the Interrupt inputs to non-inverting level interrupt
221     */
222    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
223                            0x54, &tmp);
224#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
225    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
226#endif
227    tmp = 0;
228    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
229                          0x54, tmp);
230  }
231  else {
232#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
233    printk("This is a first generation MCP750 board\n");
234    printk("We just show the actual value used by PCI/ISA bridge\n");
235#endif
236    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
237                         0x47,  &tmp);
238#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
239    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
240#endif
241    /*
242     * Show the Interrupt inputs inverting/non-inverting level status
243     */
244    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
245                         0x54, &tmp);
246#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
247    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
248#endif
249  }
250}
251
252  /*
253   * This code assumes the exceptions management setup has already
254   * been done. We just need to replace the exceptions that will
255   * be handled like interrupt. On mcp750/mpc750 and many PPC processors
256   * this means the decrementer exception and the external exception.
257   */
258void BSP_rtems_irq_mng_init(unsigned cpuId)
259{
260#if !defined(mvme2100)
261  int known_cpi_isa_bridge = 0;
262#endif
263  int i;
264
265  /*
266   * First initialize the Interrupt management hardware
267   */
268#if defined(mvme2100)
269#ifdef TRACE_IRQ_INIT
270  printk("Going to initialize EPIC interrupt controller (openpic compliant)\n");
271#endif
272  openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses);
273  /* Speed up the serial interface; if it is too slow then we might get spurious
274   * interrupts:
275   * After an ISR clears the interrupt condition at the source/device, the wire
276   * remains asserted during the propagation delay introduced by the serial interface
277   * (something really stupid). If the ISR returns while the wire is not released
278   * yet, then a spurious interrupt happens.
279   * The book says we should be careful if the serial clock is > 33MHz.
280   * Empirically, it seems that running it at 33MHz is fast enough. Otherwise,
281   * we should introduce a delay in openpic_eoi().
282   * The maximal delay are 16 (serial) clock cycles. If the divisor is 8
283   * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this
284   * is equal to the bus frequency].
285   * FIXME: This should probably be a 8240-specific piece in 'openpic.c'
286   */
287  {
288  uint32_t eicr_val, ratio;
289    /* On the 8240 this is the EICR register */
290    eicr_val = in_le32( &OpenPIC->Global.Global_Configuration1 ) & ~(7<<28);
291    if ( (1<<27) & eicr_val ) {
292      /* serial interface mode enabled */
293
294      /* round to nearest integer:
295       *   round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2
296       */
297      ratio   = BSP_bus_frequency / 16500000 + 1;
298      ratio >>= 2; /* EICR value is half actual divisor */
299      if ( 0==ratio )
300        ratio = 1;
301      out_le32(&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28));
302      /*  Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */
303      openpic_set_eoi_delay( 16 * (2*ratio) / 4 );
304    }
305  }
306#else
307#ifdef TRACE_IRQ_INIT 
308  printk("Going to initialize raven interrupt controller (openpic compliant)\n");
309#endif
310  openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses);
311#ifdef TRACE_IRQ_INIT 
312  printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n");
313#endif
314  if ( currentBoard == MESQUITE ) {
315    VIA_isa_bridge_interrupts_setup();
316    known_cpi_isa_bridge = 1;
317  }
318  if ( currentBoard == MVME_2300 ) {
319    /* nothing to do for W83C553 bridge */
320    known_cpi_isa_bridge = 1;
321  }
322  if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) {
323     /* W83C554, don't to anything at the moment.  gregm 11/6/2002 */
324     known_cpi_isa_bridge = 1;
325  }
326
327  if (!known_cpi_isa_bridge) {
328    printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n");
329    printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n");
330    printk("currentBoard = %i\n", currentBoard);
331  }
332#ifdef TRACE_IRQ_INIT
333  printk("Going to initialize the ISA PC legacy IRQ management hardware\n");
334#endif
335  BSP_i8259s_init();
336#endif
337
338  /*
339   * Initialize RTEMS management interrupt table
340   */
341    /*
342     * re-init the rtemsIrq table
343     */
344    for (i = 0; i < BSP_IRQ_NUMBER; i++) {
345      rtemsIrq[i]      = defaultIrq;
346      rtemsIrq[i].name = i;
347    }
348    /*
349     * Init initial Interrupt management config
350     */
351    initial_config.irqNb        = BSP_IRQ_NUMBER;
352    initial_config.defaultEntry = defaultIrq;
353    initial_config.irqHdlTbl    = rtemsIrq;
354    initial_config.irqBase      = BSP_ASM_IRQ_VECTOR_BASE;
355    initial_config.irqPrioTbl   = irqPrioTable;
356
357    if (!BSP_rtems_irq_mngt_set(&initial_config)) {
358      /*
359       * put something here that will show the failure...
360       */
361      BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
362    }
363 
364#ifdef TRACE_IRQ_INIT 
365    printk("RTEMS IRQ management is now operational\n");
366#endif
367}
Note: See TracBrowser for help on using the repository browser.