From 0ed348f4b81faafd8f0f8606170375375831212d Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Fri, 2 Dec 2005 20:45:57 +0000 Subject: 2005-12-02 Till Straumann * 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. --- c/src/lib/libbsp/powerpc/ChangeLog | 8 ++++++ c/src/lib/libbsp/powerpc/shared/irq/irq_init.c | 33 +++++++++++++++++++++++ c/src/lib/libbsp/powerpc/shared/openpic/openpic.c | 15 +++++++++++ c/src/lib/libbsp/powerpc/shared/openpic/openpic.h | 7 +++++ 4 files changed, 63 insertions(+) diff --git a/c/src/lib/libbsp/powerpc/ChangeLog b/c/src/lib/libbsp/powerpc/ChangeLog index f90411188e..9cfa146a43 100644 --- a/c/src/lib/libbsp/powerpc/ChangeLog +++ b/c/src/lib/libbsp/powerpc/ChangeLog @@ -1,3 +1,11 @@ +2005-12-02 Till Straumann + * 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. + 2005-12-01 Till Straumann * shared/vectors/vectors.h, shared/vectors/vectors.S, shared/vectors/vectors_init.c: Reduced size of default diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c b/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c index 231edab695..fb70847918 100644 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c +++ b/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c @@ -270,6 +270,39 @@ void BSP_rtems_irq_mng_init(unsigned cpuId) printk("Going to initialize EPIC interrupt controller (openpic compliant)\n"); #endif openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses); + /* Speed up the serial interface; if it is too slow then we might get spurious + * interrupts: + * After an ISR clears the interrupt condition at the source/device, the wire + * remains asserted during the propagation delay introduced by the serial interface + * (something really stupid). If the ISR returns while the wire is not released + * yet, then a spurious interrupt happens. + * The book says we should be careful if the serial clock is > 33MHz. + * Empirically, it seems that running it at 33MHz is fast enough. Otherwise, + * we should introduce a delay in openpic_eoi(). + * The maximal delay are 16 (serial) clock cycles. If the divisor is 8 + * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this + * is equal to the bus frequency]. + * FIXME: This should probably be a 8240-specific piece in 'openpic.c' + */ + { + uint32_t eicr_val, ratio; + /* On the 8240 this is the EICR register */ + eicr_val = in_le32( &OpenPIC->Global.Global_Configuration1 ) & ~(7<<28); + if ( (1<<27) & eicr_val ) { + /* serial interface mode enabled */ + + /* round to nearest integer: + * round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2 + */ + ratio = BSP_bus_frequency / 16500000 + 1; + ratio >>= 2; /* EICR value is half actual divisor */ + if ( 0==ratio ) + ratio = 1; + out_le32(&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28)); + /* Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */ + openpic_set_eoi_delay( 16 * (2*ratio) / 4 ); + } + } #else #ifdef TRACE_IRQ_INIT printk("Going to initialize raven interrupt controller (openpic compliant)\n"); diff --git a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c b/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c index 80af4d897b..ab9b8c49da 100644 --- a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c +++ b/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c @@ -39,6 +39,10 @@ volatile struct OpenPIC *OpenPIC = NULL; static unsigned int NumProcessors; static unsigned int NumSources; +#if defined(mpc8240) || defined(mpc8245) +static unsigned int openpic_eoi_delay = 0; +#endif + /* * Accesses to the current processor's registers */ @@ -312,9 +316,20 @@ unsigned int openpic_irq(unsigned int cpu) void openpic_eoi(unsigned int cpu) { check_arg_cpu(cpu); +#if defined(mpc8240) || defined(mpc8245) + if ( openpic_eoi_delay ) + rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay); +#endif openpic_write(&OpenPIC->THIS_CPU.EOI, 0); } +#if defined(mpc8240) || defined(mpc8245) +void openpic_set_eoi_delay(unsigned tb_cycles) +{ + openpic_eoi_delay = tb_cycles; +} +#endif + /* * Get/set the current task priority */ diff --git a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.h b/c/src/lib/libbsp/powerpc/shared/openpic/openpic.h index e70a55605b..492742188f 100644 --- a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.h +++ b/c/src/lib/libbsp/powerpc/shared/openpic/openpic.h @@ -43,6 +43,13 @@ #if defined(mpc8240) || defined(mpc8245) #define OPENPIC_MAX_SOURCES (2048 - 16) +/* If the BSP uses the serial interrupt mode / 'multiplexer' then + * EOI must be delayed by at least 16 SRAM_CLK cycles to avoid + * spurious interrupts. + * It is the BSP's responsibility to set up an appropriate delay + * (in timebase-clock cycles) at init time. + */ +extern void openpic_set_eoi_delay(unsigned tb_cycles); #else #define OPENPIC_MAX_SOURCES 2048 #endif -- cgit v1.2.3