/* $Id$ */
/* Standard VME bridge configuration for MVME5500, MVME6100 */
/*
* Authorship
* ----------
* This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
* created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The 'beatnik' BSP was produced by
* the Stanford Linear Accelerator Center, Stanford University,
* under Contract DE-AC03-76SFO0515 with the Department of Energy.
*
* Government disclaimer of liability
* ----------------------------------
* Neither the United States nor the United States Department of Energy,
* nor any of their employees, makes any warranty, express or implied, or
* assumes any legal liability or responsibility for the accuracy,
* completeness, or usefulness of any data, apparatus, product, or process
* disclosed, or represents that its use would not infringe privately owned
* rights.
*
* Stanford disclaimer of liability
* --------------------------------
* Stanford University makes no representations or warranties, express or
* implied, nor assumes any liability for the use of this software.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#include <rtems.h>
#include <rtems/bspIo.h>
#include <bsp.h>
#include <bsp/VME.h>
#include <bsp/VMEConfig.h>
#include <bsp/irq.h>
#include <bsp/vmeUniverse.h>
#define _VME_TSI148_DECLARE_SHOW_ROUTINES
#include <bsp/vmeTsi148.h>
#include <libcpu/bat.h>
/* Use a weak alias for the VME configuration.
* This permits individual applications to override
* this routine.
* They may even create an 'empty'
*
* void BSP_vme_config(void) {}
*
* which will avoid linking in the Universe driver
* at all :-).
*/
void BSP_vme_config(void) __attribute__ (( weak, alias("__BSP_default_vme_config") ));
typedef struct {
int (*xlate_adrs)(int, int, unsigned long, unsigned long, unsigned long *);
int (*install_isr)(unsigned long, BSP_VME_ISR_t, void *);
int (*remove_isr)(unsigned long, BSP_VME_ISR_t, void *);
BSP_VME_ISR_t (*get_isr)(unsigned long vector, void **);
int (*enable_int_lvl)(unsigned int);
int (*disable_int_lvl)(unsigned int);
int (*outbound_p_cfg)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
int (*inbound_p_cfg) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
void (*outbound_p_show)(FILE*);
void (*inbound_p_show) (FILE*);
void (*reset_bus)(void);
int (*install_irq_mgr)(int, int, int, ...);
} VMEOpsRec, *VMEOps;
static VMEOpsRec uniOpsRec = {
xlate_adrs: vmeUniverseXlateAddr,
install_isr: vmeUniverseInstallISR,
remove_isr: vmeUniverseRemoveISR,
get_isr: vmeUniverseISRGet,
enable_int_lvl: vmeUniverseIntEnable,
disable_int_lvl: vmeUniverseIntDisable,
outbound_p_cfg: vmeUniverseMasterPortCfg,
inbound_p_cfg: vmeUniverseSlavePortCfg,
outbound_p_show: vmeUniverseMasterPortsShow,
inbound_p_show: vmeUniverseSlavePortsShow,
reset_bus: vmeUniverseResetBus,
install_irq_mgr: vmeUniverseInstallIrqMgrAlt,
};
static VMEOpsRec tsiOpsRec = {
xlate_adrs: vmeTsi148XlateAddr,
install_isr: vmeTsi148InstallISR,
remove_isr: vmeTsi148RemoveISR,
get_isr: vmeTsi148ISRGet,
enable_int_lvl: vmeTsi148IntEnable,
disable_int_lvl: vmeTsi148IntDisable,
outbound_p_cfg: vmeTsi148OutboundPortCfg,
inbound_p_cfg: vmeTsi148InboundPortCfg,
outbound_p_show: vmeTsi148OutboundPortsShow,
inbound_p_show: vmeTsi148InboundPortsShow,
reset_bus: vmeTsi148ResetBus,
install_irq_mgr: vmeTsi148InstallIrqMgrAlt,
};
static VMEOps theOps = 0;
int
BSP_vme2local_adrs(unsigned long am, unsigned long vmeaddr, unsigned long *plocaladdr)
{
int rval=theOps->xlate_adrs(1,0,am,vmeaddr,plocaladdr);
*plocaladdr+=PCI_MEM_BASE;
return rval;
}
int
BSP_local2vme_adrs(unsigned long am, unsigned long localaddr, unsigned long *pvmeaddr)
{
return theOps->xlate_adrs(0, 0, am,localaddr+PCI_DRAM_OFFSET,pvmeaddr);
}
int
BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
{
return theOps->install_isr(vector, handler, arg);
}
int
BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
{
return theOps->remove_isr(vector, handler, arg);
}
/* retrieve the currently installed ISR for a given vector */
BSP_VME_ISR_t
BSP_getVME_isr(unsigned long vector, void **parg)
{
return theOps->get_isr(vector, parg);
}
int
BSP_enableVME_int_lvl(unsigned int level)
{
return theOps->enable_int_lvl(level);
}
int
BSP_disableVME_int_lvl(unsigned int level)
{
return theOps->disable_int_lvl(level);
}
int
BSP_VMEOutboundPortCfg(
unsigned long port,
unsigned long address_space,
unsigned long vme_address,
unsigned long pci_address,
unsigned long size)
{
return theOps->outbound_p_cfg(port, address_space, vme_address, pci_address, size);
}
int
BSP_VMEInboundPortCfg(
unsigned long port,
unsigned long address_space,
unsigned long vme_address,
unsigned long pci_address,
unsigned long size)
{
return theOps->inbound_p_cfg(port, address_space, vme_address, pci_address, size);
}
void
BSP_VMEOutboundPortsShow(FILE *f)
{
theOps->outbound_p_show(f);
}
void
BSP_VMEInboundPortsShow(FILE *f)
{
theOps->inbound_p_show(f);
}
void
BSP_VMEResetBus(void)
{
theOps->reset_bus();
}
static unsigned short
tsi_clear_errors(int quiet)
{
unsigned long v;
unsigned short rval;
v = vmeTsi148ClearVMEBusErrors(0);
/* return bits 8..23 of VEAT; set bit 15 to make sure rval is nonzero on error */
rval = v ? ((v>>8) & 0xffff) | (1<<15) : 0;
return rval;
}
void
__BSP_default_vme_config(void)
{
int err = 1;
if ( 0 == vmeUniverseInit() ) {
theOps = &uniOpsRec;
vmeUniverseReset();
} else if ( 0 == vmeTsi148Init() ) {
theOps = &tsiOpsRec;
vmeTsi148Reset();
_BSP_clear_vmebridge_errors = tsi_clear_errors;
} else
return; /* no VME bridge found chip */
/* map VME address ranges */
BSP_VMEOutboundPortCfg(
0,
VME_AM_EXT_SUP_DATA,
_VME_A32_WIN0_ON_VME,
_VME_A32_WIN0_ON_PCI,
0x0e000000
);
BSP_VMEOutboundPortCfg(
1,
VME_AM_STD_SUP_DATA,
0x00000000,
_VME_A24_ON_PCI,
0x00ff0000);
BSP_VMEOutboundPortCfg(
2,
VME_AM_SUP_SHORT_IO,
0x00000000,
_VME_A16_ON_PCI,
0x00010000);
#ifdef _VME_CSR_ON_PCI
/* Map VME64 CSR */
BSP_VMEOutboundPortCfg(
7,
VME_AM_CSR,
0,
_VME_CSR_ON_PCI,
0x01000000);
#endif
#ifdef _VME_DRAM_OFFSET
/* map our memory to VME */
BSP_VMEInboundPortCfg(
0,
VME_AM_EXT_SUP_DATA | VME_AM_IS_MEMORY,
_VME_DRAM_OFFSET,
PCI_DRAM_OFFSET,
BSP_mem_size);
#endif
/* stdio is not yet initialized; the driver will revert to printk */
BSP_VMEOutboundPortsShow(0);
BSP_VMEInboundPortsShow(0);
switch (BSP_getBoardType()) {
case MVME6100:
err = theOps->install_irq_mgr(
VMETSI148_IRQ_MGR_FLAG_SHARED,
0, BSP_IRQ_GPP_0 + 20,
1, BSP_IRQ_GPP_0 + 21,
2, BSP_IRQ_GPP_0 + 22,
3, BSP_IRQ_GPP_0 + 23,
-1);
break;
case MVME5500:
err = theOps->install_irq_mgr(
VMEUNIVERSE_IRQ_MGR_FLAG_SHARED |
VMEUNIVERSE_IRQ_MGR_FLAG_PW_WORKAROUND,
0, BSP_IRQ_GPP_0 + 12,
1, BSP_IRQ_GPP_0 + 13,
2, BSP_IRQ_GPP_0 + 14,
3, BSP_IRQ_GPP_0 + 15,
-1);
break;
default:
printk("WARNING: unknown board; ");
break;
}
if ( err )
printk("VME interrupt manager NOT INSTALLED (error: %i)\n", err);
}