From 82948ea1b5858ac3671d7196aebd20a35b10592c Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 8 May 2009 18:37:08 +0000 Subject: 2009-05-08 Kate Feng PR1395/bsps * Updated the changes from RTEMS-4.8.0, which were made since Oct. 2007. * network/if_1GHz/if_wm.c: fixed some bugs in the 1GHz driver. * pci/pci_interface.c: + Enabled PCI "Read", "Read Line", and "Read Multiple" + Agressive Prefetch to improve the performance of the PCI based applications (e.g. 1GHz NIC). * irq/BSP_irq.c : Replaced the irq/irq.c, and used GT_GPP_Value register to monitor the cause of the level sensitive interrupts. This unique solution solves various bugs in the 1GHz network drivers Fixed bugs in compute_pic_masks_from_prio() * pci/pci.c : Updated it to be consistent with the original pci.c * written by Eric Valette. There is no change in its function. * irq/irq_init.c : set defaultIrq->next_handler to be 0 * for BSP_SHARED_HANDLER_SUPPORT. --- c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c | 492 ++++++++++++++++++++++++ 1 file changed, 492 insertions(+) create mode 100644 c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c (limited to 'c/src') diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c new file mode 100644 index 0000000000..25d2a92e3d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c @@ -0,0 +1,492 @@ +/* BSP_irq.c + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Acknowledgement May 2004, to Till Straumann + * for some inputs. + * + * Copyright 2003, 2004, 2005, 2007 Shuchen Kate Feng , + * NSLS, Brookhaven National Laboratory. All rights reserved. + * + * 1) Used GT_GPP_Value register instead of the GT_GPP_Interrupt_Cause + * register to monitor the cause of the level sensitive interrupts. + * (Copyright : NDA item) + * 2) The implementation of picPrioTable[] is an original work by the + * author to optimize the software IRQ priority scheduling because + * Discovery controller does not provide H/W IRQ priority schedule. + * It ensures the fastest/faster interrupt service to the + * highest/higher priority IRQ, if pendig. + * 3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER() + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for printk */ +#include "bsp/gtreg.h" + +#define HI_INT_CAUSE 0x40000000 + +#define MAX_IRQ_LOOP 20 + +/* #define DEBUG_IRQ*/ + +/* + * pointer to the mask representing the additionnal irq vectors + * that must be disabled when a particular entry is activated. + * They will be dynamically computed from the table given + * in BSP_rtems_irq_mngt_set(); + * CAUTION : this table is accessed directly by interrupt routine + * prologue. + */ +static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER]; + +/* + * location used to store initial tables used for interrupt + * management.BSP copy of the configuration + */ +static rtems_irq_global_settings BSP_config; +static rtems_irq_connect_data* rtems_hdl_tbl; + +/* + * default handler connected on each irq after bsp initialization + * (locally cached copy) + */ +void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1; + + +static volatile unsigned *BSP_irqMask_reg[3]; +static volatile unsigned *BSP_irqCause_reg[3]; +static volatile unsigned BSP_irqMask_cache[3]={0,0,0}; + +static int picPrioTblPtr=0; +static unsigned int GPPIrqInTbl=0; +static unsigned long long MainIrqInTbl=0; + +/* + * The software developers are forbidden to setup picPrioTable[], + * as it is a powerful engine for the BSP to find the pending + * highest priority IRQ at run time. It ensures the fastest/faster + * interrupt service to the highest/higher priority IRQ, if pendig. + * + * The picPrioTable[96] is updated dynamically at run time + * based on the priority levels set at BSPirqPrioTable[96], + * while the BSP_enable_irq_at_pic(), and BSP_disable_irq_at_pic() + * commands are invoked. + * + * The picPrioTable[96] lists the enabled CPU main and GPP external interrupt + * numbers [0 (lowest)- 95 (highest)] starting from the highest priority + * one to the lowest priority one. The highest priority interrupt is + * located at picPrioTable[0], and the lowest priority interrupt is located + * at picPrioTable[picPrioTblPtr-1]. + * + * + */ +#define DynamicIsrTable +#ifdef DynamicIsrTable +/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */ +static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1 }; +#else +static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ + 80, 84, 76, 77, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1 }; +#endif + +/* + * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ + */ +static inline int is_pic_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET) + ); +} + +/* + * Check if IRQ is a Porcessor IRQ + */ +static inline int is_processor_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) + ); +} + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +/* + * Caution : this function assumes the variable "BSP_config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_pic_masks_from_prio(void) +{ + int i,j, k, isGppMain; + unsigned long long irq_prio_mask=0; + + /* + * Always mask at least current interrupt to prevent re-entrance + */ + for (i=0; i a equal priority. + */ + if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j]) + irq_prio_mask |= (unsigned long long)(1LLU << j); + } + + + BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff; + BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff; +#if 0 + printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i], + BSP_irq_prio_mask_tbl[0][i]); +#endif + + BSP_irq_prio_mask_tbl[2][i] = 1<= BSP_config.irqPrioTbl [j]) + BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET); + } +#if 0 + printk("GPPirq_mask_prio_tbl[%d]:0x%8x\n",i,BSP_irq_prio_mask_tbl[2][i]); +#endif + } +} + +static void UpdateMainIrqTbl(int irqNum) +{ + int i=0, j, shifted=0; + + switch (irqNum) { + case BSP_MAIN_GPP7_0_IRQ: + case BSP_MAIN_GPP15_8_IRQ: + case BSP_MAIN_GPP23_16_IRQ: + case BSP_MAIN_GPP31_24_IRQ: + return; /* Do nothing, let GPP take care of it */ + break; + } +#ifdef SHOW_MORE_INIT_SETTINGS + unsigned long val2, val1; +#endif + + /* If entry not in table*/ + if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && + (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))) + { + while ( picPrioTable[i]!=-1) { + if (BSP_config.irqPrioTbl[irqNum]>BSP_config.irqPrioTbl[picPrioTable[i]]) { + /* all other lower priority entries shifted right */ + for (j=picPrioTblPtr;j>i; j--) { + picPrioTable[j]=picPrioTable[j-1]; + } + picPrioTable[i]=irqNum; + shifted=1; + break; + } + i++; + } + if (!shifted) picPrioTable[picPrioTblPtr] =irqNum; + + if (irqNum >BSP_MICH_IRQ_MAX_OFFSET) + GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); + else + MainIrqInTbl |= (unsigned long long)(1LLU << irqNum); + picPrioTblPtr++; + } +#ifdef SHOW_MORE_INIT_SETTINGS + val2 = (MainIrqInTbl>>32) & 0xffffffff; + val1 = MainIrqInTbl&0xffffffff; + printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1); + BSP_printPicIsrTbl(); +#endif + +} + + +static void CleanMainIrqTbl(int irqNum) +{ + int i, j; + + switch (irqNum) { + case BSP_MAIN_GPP7_0_IRQ: + case BSP_MAIN_GPP15_8_IRQ: + case BSP_MAIN_GPP23_16_IRQ: + case BSP_MAIN_GPP31_24_IRQ: + return; /* Do nothing, let GPP take care of it */ + break; + } + if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && + (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))) + { /* If entry in table*/ + for (i=0; i<64; i++) { + if (picPrioTable[i]==irqNum) {/*remove it from the entry */ + /* all other lower priority entries shifted left */ + for (j=i;jBSP_MICH_IRQ_MAX_OFFSET) + GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); + else + MainIrqInTbl &= ~(1LLU << irqNum); + picPrioTblPtr--; + break; + } + } + } +} + +void BSP_enable_irq_at_pic(const rtems_irq_number irqNum) +{ + unsigned bitNum, regNum; + unsigned int level; + + if ( !is_pic_irq(irqNum) ) + return; + + bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; + regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; + + rtems_interrupt_disable(level); + +#ifdef DynamicIsrTable + UpdateMainIrqTbl((int) irqNum); +#endif + BSP_irqMask_cache[regNum] |= (1 << bitNum); + + out_le32(BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]); + while (in_le32(BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]); + + rtems_interrupt_enable(level); +} + +void BSP_enable_pic_irq(const rtems_irq_number irqNum) +{ + BSP_enable_irq_at_pic(irqNum); +} + +int BSP_disable_irq_at_pic(const rtems_irq_number irqNum) +{ + int rval; + unsigned bitNum, regNum; + unsigned int level; + + if ( ! is_pic_irq(irqNum) ) + return -1; + + bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; + regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; + + rtems_interrupt_disable(level); + +#ifdef DynamicIsrTable + CleanMainIrqTbl((int) irqNum); +#endif + + rval = BSP_irqMask_cache[regNum] & (1<defaultEntry.hdl; + rtems_hdl_tbl = config->irqHdlTbl; + + /* Get ready for discovery BSP */ + BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_LO); + BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_HI); + BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_LO); + BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_HI); + BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Interrupt_Mask); + BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Value); + + /* Page 401, Table 598: + * Comm Unit Arbiter Control register : + * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0). + * MOTload default is set as level sensitive(1). Set it agin to make sure. + */ + out_le32(GT_CommUnitArb_Ctrl, (in_le32(GT_CommUnitArb_Ctrl)| (1<<10))); + +#if 0 + printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n", + in_le32(BSP_irqMask_reg[0]), + in_le32(BSP_irqCause_reg[0])); + printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n", + in_le32(BSP_irqMask_reg[1]), + in_le32(BSP_irqCause_reg[1])); + printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n", + in_le32(BSP_irqMask_reg[2]), + in_le32(BSP_irqCause_reg[2])); +#endif + + /* Initialize the interrupt related registers */ + for (i=0; i<3; i++) { + out_le32(BSP_irqCause_reg[i], 0); + out_le32(BSP_irqMask_reg[i], 0); + } + in_le32(BSP_irqMask_reg[2]); + compute_pic_masks_from_prio(); + +#if 0 + printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n", + in_le32(BSP_irqMask_reg[0]), + in_le32(BSP_irqCause_reg[0])); + printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n", + in_le32(BSP_irqMask_reg[1]), + in_le32(BSP_irqCause_reg[1])); + printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n", + in_le32(BSP_irqMask_reg[2]), + in_le32(BSP_irqCause_reg[2])); +#endif + + /* + * + */ + for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) { + if ( BSP_config.irqHdlTbl[i].hdl != BSP_config.defaultEntry.hdl) { + BSP_enable_irq_at_pic(i); + BSP_config.irqHdlTbl[i].on(&BSP_config.irqHdlTbl[i]); + } + else { + BSP_config.irqHdlTbl[i].off(&BSP_config.irqHdlTbl[i]); + BSP_disable_irq_at_pic(i); + } + } + for (i= BSP_MAIN_GPP7_0_IRQ; i < BSP_MAIN_GPP31_24_IRQ; i++) + BSP_enable_irq_at_pic(i); + + return(1); +} + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + unsigned long irqCause[3]={0, 0,0}; + unsigned oldMask[3]={0,0,0}; + int loop=0, wloop=0, i=0, j; + int irq=0, group=0; + + if (excNum == ASM_DEC_VECTOR) { + bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl); + return 0; + } + + for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j]; + for (j=0; j<3; j++) irqCause[j] = in_le32(BSP_irqCause_reg[j]) & in_le32(BSP_irqMask_reg[j]); + + while (((irq = picPrioTable[i++])!=-1)&& (loop++ < MAX_IRQ_LOOP)) + { + if (irqCause[group= irq/32] & ( 1<<(irq % 32))) { + for (j=0; j<3; j++) + BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]); + + out_le32(BSP_irqMask_reg[0], BSP_irqMask_cache[0]); + out_le32(BSP_irqMask_reg[1], BSP_irqMask_cache[1]); + out_le32(BSP_irqMask_reg[2], BSP_irqMask_cache[2]); + in_le32(BSP_irqMask_reg[2]); + + bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl); + + for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j]; + + out_le32(BSP_irqMask_reg[0], oldMask[0]); + out_le32(BSP_irqMask_reg[1], oldMask[1]); + out_le32(BSP_irqMask_reg[2], oldMask[2]); + in_le32(BSP_irqMask_reg[2]); + } + } + + return 0; +} + +/* Only print part of the entries for now */ +void BSP_printPicIsrTbl() +{ + int i; + + printf("picPrioTable[12]={ {irq# : "); + for (i=0; i<12; i++) + printf("%d,", picPrioTable[i]); + printf("}\n"); + + printf("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl); +} -- cgit v1.2.3