diff options
Diffstat (limited to 'bsps/include/bsp')
-rw-r--r-- | bsps/include/bsp/VME.h | 133 | ||||
-rw-r--r-- | bsps/include/bsp/VMEDMA.h | 309 | ||||
-rw-r--r-- | bsps/include/bsp/bootcard.h | 188 | ||||
-rw-r--r-- | bsps/include/bsp/bspVmeDmaList.h | 140 | ||||
-rw-r--r-- | bsps/include/bsp/console-polled.h | 43 | ||||
-rw-r--r-- | bsps/include/bsp/console-termios.h | 117 | ||||
-rw-r--r-- | bsps/include/bsp/default-initial-extension.h | 53 | ||||
-rw-r--r-- | bsps/include/bsp/fatal.h | 153 | ||||
-rw-r--r-- | bsps/include/bsp/fdt.h | 67 | ||||
-rw-r--r-- | bsps/include/bsp/gpio.h | 955 | ||||
-rw-r--r-- | bsps/include/bsp/irq-generic.h | 304 | ||||
-rw-r--r-- | bsps/include/bsp/irq-info.h | 56 | ||||
-rw-r--r-- | bsps/include/bsp/mm.h | 41 | ||||
-rw-r--r-- | bsps/include/bsp/stackalloc.h | 94 | ||||
-rw-r--r-- | bsps/include/bsp/u-boot.h | 66 | ||||
-rw-r--r-- | bsps/include/bsp/uart-output-char.h | 60 | ||||
-rw-r--r-- | bsps/include/bsp/utility.h | 156 | ||||
-rw-r--r-- | bsps/include/bsp/vmeTsi148.h | 662 | ||||
-rw-r--r-- | bsps/include/bsp/vmeTsi148DMA.h | 102 | ||||
-rw-r--r-- | bsps/include/bsp/vmeUniverse.h | 1045 | ||||
-rw-r--r-- | bsps/include/bsp/vmeUniverseDMA.h | 95 | ||||
-rw-r--r-- | bsps/include/bsp/vme_am_defs.h | 198 |
22 files changed, 5037 insertions, 0 deletions
diff --git a/bsps/include/bsp/VME.h b/bsps/include/bsp/VME.h new file mode 100644 index 0000000000..bdaa45870e --- /dev/null +++ b/bsps/include/bsp/VME.h @@ -0,0 +1,133 @@ +/** + * @file + * + * @ingroup shared_vme + * + * @brief SVGM et al. BSP's VME support + */ + +#ifndef RTEMS_BSP_VME_API_H +#define RTEMS_BSP_VME_API_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 <stdio.h> + +/* address modifiers & friends */ +#include <bsp/vme_am_defs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup shared_vme VME related declarations + * + * @ingroup shared_vmeuniverse + * + * @brief BSP-specific configuration routine; sets up + * VME windows and installs the VME interrupt manager. + */ + +void BSP_vme_config(); + +/* translate through host bridge and vme master window of vme bridge */ +int +BSP_vme2local_adrs(unsigned long am, unsigned long vmeaddr, unsigned long *plocaladdr); + +/* how a CPU address is mapped to the VME bus (if at all) */ +int +BSP_local2vme_adrs(unsigned long am, unsigned long localaddr, unsigned long *pvmeaddr); + +/* interrupt handlers and levels */ +typedef void (*BSP_VME_ISR_t)(void *usrArg, unsigned long vector); + +int +BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg); +int +BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg); + +/* retrieve the currently installed ISR for a given vector */ +BSP_VME_ISR_t +BSP_getVME_isr(unsigned long vector, void **parg); + +int +BSP_enableVME_int_lvl(unsigned int level); + +int +BSP_disableVME_int_lvl(unsigned int level); + +int +BSP_VMEOutboundPortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long size); + +int +BSP_VMEInboundPortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long size); + +void +BSP_VMEOutboundPortsShow(FILE *f); + +void +BSP_VMEInboundPortsShow(FILE *f); + +/* Assert VME SYSRESET */ +void +BSP_VMEResetBus(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/VMEDMA.h b/bsps/include/bsp/VMEDMA.h new file mode 100644 index 0000000000..636f6d365c --- /dev/null +++ b/bsps/include/bsp/VMEDMA.h @@ -0,0 +1,309 @@ +/** + * @file + * + * @ingroup shared_vmedma + * + * @brief Public interface of DMA routines + */ + +#ifndef BSP_VME_DMA_H +#define BSP_VME_DMA_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2006, 2007 + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup shared_vmedma VMEDMA Support + * + * @ingroup shared_vmeuniverse + * + * @brief VMEDMA Support Package + */ + + +/* NOTE: Access to DMA Channels is *not* protected / thread-safe. + * It is the responsability of the user to provide appropriate + * locking/serialization. + */ + +/* Simple abstraction of DMA controller setup / bus utilization: */ + +/* Since VME is the bottleneck, the settings for PCI are always + * chosen aggressively. + */ + + +/* Optimize for throughput; accept longer latencies: + * Choose a large block size (1k) and immediately re-request + * the bus at block boundaries. + */ +#define BSP_VMEDMA_OPT_THROUGHPUT 1 +/* Optimize for latency, accept throughput penalty: + * Choose a small block size (32b) and immediately re-request + * the bus at block boundaries. + */ +#define BSP_VMEDMA_OPT_LOWLATENCY 2 + +/* Optimize for bus sharing with other devices: + * Choose relatively small block size (128) and back off for 64us + * at each block boundary. + */ +#define BSP_VMEDMA_OPT_SHAREDBUS 3 + +/* Choose bridge default/reset configuration: + * (see manual) + */ +#define BSP_VMEDMA_OPT_DEFAULT 4 + +/* Provide custom configuration pass pointer to array + * with as many 32-bit words the particular bridge chip + * expects. + */ +#define BSP_VMEDMA_OPT_CUSTOM 5 + +/* VME Transfer modes */ + +/* Bitwise OR of the VME address-modifier/transfer-type + * with driver specific (no standard AM code for 2eVME and + * 2eSST defined) and optional special flags (see below) + */ + +/* Additional qualifiers: */ + +/* Don't increment VME address */ +#define BSP_VMEDMA_MODE_NOINC_VME (1<<20) +/* Don't increment PCI address */ +#define BSP_VMEDMA_MODE_NOINC_PCI (1<<21) + +/* Direction */ +#define BSP_VMEDMA_MODE_PCI2VME (1<<31) + +typedef void *BSP_VMEDmaListDescriptor; + +/* Program the device for the selected mode; + * + * 'bus_mode': one of the ...VMEDMA_OPT... choices + * listed above. + * 'xfer_mode': VME address-modifier optionally ORed with + * ...VMEDMA_MODE... bits listed above. + * 'custom': (only used if bus_mode is VMEDMA_OPT_CUSTOM) + * pointer to a list of setup parameters (chip-driver + * specific). + * + * RETURNS: 0 on success, nonzero on error (mode or channel + * unsupported). + * + * NOTES: The setup is preserved across multiple DMA transfers. + * It is the responsibility of the driver to reprogram + * the setup if the hardware does not preserve it. + * However - in linked list mode, some fields may be + * read from the list descriptors. + * + * Usually this routine must be used even in linked-list + * mode to program the 'bus_mode'. + * + * Direction of transfer is specified by a bit in the + * 'xfer_mode' (BSP_VMEDMA_MODE_PCI2VME). + */ +int +BSP_VMEDmaSetup(int channel, uint32_t bus_mode, uint32_t xfer_mode, void *custom_setup); + +/* Start direct (not linked-list) transfer. + * + * RETURNS: 0 on success, nonzero on failure + */ +int +BSP_VMEDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes); + +/* Transfer status/result */ +#define BSP_VMEDMA_STATUS_OK 0 +/* Unsupported channel */ +#define BSP_VMEDMA_STATUS_UNSUP (-1) +/* Bus error on VME */ +#define BSP_VMEDMA_STATUS_BERR_VME 1 +/* Bus error on PCI */ +#define BSP_VMEDMA_STATUS_BERR_PCI 2 +/* Channel busy */ +#define BSP_VMEDMA_STATUS_BUSY 3 +/* Setup/programming error */ +#define BSP_VMEDMA_STATUS_PERR 4 +/* Other/unspecified error */ +#define BSP_VMEDMA_STATUS_OERR 5 + +/* Retrieve status of last transfer. + * + * RETURNS: 0 if the transfer was successful, + * nonzero on error (e.g., one of the + * values defined above). + * + * NOTE: Driver is allowed to pass other, + * device specific codes + */ + +uint32_t +BSP_VMEDmaStatus(int channel); + +/* + * Hook a callback (executed from ISR context) to DMA interrupt and + * enable it. + * If called with NULL callback then an existing callback is removed + * and the interrupt disabled. + * + * RETURNS: 0 on success, nonzero on failure (IRQ in use, unsupported + * channel). + */ +typedef void (*BSP_VMEDmaIRQCallback)(void *usr_arg); + +int +BSP_VMEDmaInstallISR(int channel, BSP_VMEDmaIRQCallback cb, void *usr_arg); + +/* + * DMA List operations. + * + * Note that the list is totally unprotected, i.e., the user is + * responsible for maintaining coherency against concurrent + * access by multiple threads or hardware. + * We assume the user builds/updates a list, hands it over to + * the hardware (list start command) and leaves it alone until + * the DMA controller is done with it. + */ + +/* Modify a list entry. If the list element pointer is NULL + * then a new list element is allocated. + * Only the fields with its corresponding bit set in the mask + * argument are touched. + * + * RETURNS: 'd' or newly allocated descriptor or NULL (no memory, + * or invalid setup). + */ +#define BSP_VMEDMA_MSK_ATTR (1<<0) +#define BSP_VMEDMA_MSK_PCIA (1<<1) +#define BSP_VMEDMA_MSK_VMEA (1<<2) +#define BSP_VMEDMA_MSK_BCNT (1<<3) +#define BSP_VMEDMA_MSK_ALL (0xf) +BSP_VMEDmaListDescriptor +BSP_VMEDmaListDescriptorSetup( + BSP_VMEDmaListDescriptor d, + uint32_t attr_mask, + uint32_t xfer_mode, + uint32_t pci_addr, + uint32_t vme_addr, + uint32_t n_bytes); + +/* De-allocate a list descriptor previously obtained by + * BSP_VMEDmaListDescriptorSetup(0,...); + * + * RETURNS: 0 on success, nonzero on failure (d currently on a list) + */ +int +BSP_VMEDmaListDescriptorDestroy(BSP_VMEDmaListDescriptor d); + +/* Traverse a list of descriptors and destroy all elements */ +int +BSP_VMEDmaListDestroy(BSP_VMEDmaListDescriptor anchor); + +/* Enqueue a list descriptor 'd' after 'tail' + * + * If 'tail' is NULL then 'd' is removed from + * the list it is currently on. + * + * RETURNS: 0 on success, nonzero if 'd' is already + * on a list (enqueue) or if it is not currently + * on a list (dequeue). + * + * NOTE: it is obviously the user's responsibility to update + * list queue/tail pointers when changing the + * structure of the list. + */ +int +BSP_VMEDmaListDescriptorEnq( + BSP_VMEDmaListDescriptor tail, + BSP_VMEDmaListDescriptor d); + +/* Obtain next and previous descriptors */ +BSP_VMEDmaListDescriptor +BSP_VMEDmaListDescriptorNext(BSP_VMEDmaListDescriptor d); + +BSP_VMEDmaListDescriptor +BSP_VMEDmaListDescriptorPrev(BSP_VMEDmaListDescriptor d); + +/* Set and get a 'usrData' pointer in the descriptor */ +void +BSP_VMEDmaListDescriptorSetUsr(BSP_VMEDmaListDescriptor d, void *usrData); + +void * +BSP_VMEDmaListDescriptorGetUsr(BSP_VMEDmaListDescriptor d); + +/* Refresh an entire list. Some DMA controllers modify certain + * fields (e.g., byte count) and this command restores the original + * setup. + */ + +int +BSP_VMEDmaListRefresh(BSP_VMEDmaListDescriptor anchor); + +/* Start linked-list operation. + * + * RETURNS: 0 on success, nonzero on failure + */ +int +BSP_VMEDmaListStart(int channel, BSP_VMEDmaListDescriptor list); + +#ifdef DEBUG +void +BSP_VMEDmaListDump(BSP_VMEDmaListDescriptor p); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/bootcard.h b/bsps/include/bsp/bootcard.h new file mode 100644 index 0000000000..aaac42e8e2 --- /dev/null +++ b/bsps/include/bsp/bootcard.h @@ -0,0 +1,188 @@ +/** + * @file + * + * @ingroup bsp_bootcard + * + * @brief Standard system startup. + */ + +/* + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_BOOTCARD_H +#define LIBBSP_SHARED_BOOTCARD_H + +#include <string.h> + +#include <rtems/config.h> +#include <rtems/bspIo.h> +#include <rtems/malloc.h> +#include <rtems/score/wkspace.h> + +#include <bspopts.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup shared_bootcard Bootcard + * + * @ingroup bsp_shared + * + * @brief Standard system startup. + * + * @{ + */ + +/** + * @brief Global pointer to the command line of boot_card(). + */ +extern const char *bsp_boot_cmdline; + +void bsp_start(void); + +void bsp_predriver_hook(void); + +void bsp_reset(void); + +/** + * @brief Standard system initialization procedure. + * + * You may pass a command line in @a cmdline. It is later available via the + * global @ref bsp_boot_cmdline variable. + * + * This is the C entry point for ALL RTEMS BSPs. It is invoked from the + * assembly language initialization file usually called @c start.S which does + * the basic CPU setup (stack, C runtime environment, zero BSS, load other + * sections) and calls afterwards boot_card(). The boot card function provides + * the framework for the BSP initialization sequence. For the basic flow of + * initialization see RTEMS C User's Guide, Initialization Manager. + * + * This style of initialization ensures that the C++ global constructors are + * executed after RTEMS is initialized. + */ +void boot_card(const char *cmdline) RTEMS_NO_RETURN; + +#ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK + /** + * @brief Gives the BSP a chance to reduce the work area size with sbrk() + * adding more later. + * + * bsp_sbrk_init() may reduce the work area size passed in. The routine + * returns the 'sbrk_amount' to be used when extending the heap. Note that + * the return value may be zero. + * + * In case the @a area size is altered, then the remaining size of the + * @a area must be greater than or equal to @a min_size. + */ + ptrdiff_t bsp_sbrk_init(Heap_Area *area, uintptr_t min_size); +#endif + +static inline void bsp_work_area_initialize_default( + void *area_begin, + uintptr_t area_size +) +{ + Heap_Area area = { + .begin = area_begin, + .size = area_size + }; + + #if BSP_DIRTY_MEMORY == 1 + memset(area.begin, 0xCF, area.size); + #endif + + #ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK + { + uintptr_t overhead = _Heap_Area_overhead(CPU_HEAP_ALIGNMENT); + uintptr_t work_space_size = rtems_configuration_get_work_space_size(); + ptrdiff_t sbrk_amount = bsp_sbrk_init( + &area, + work_space_size + + overhead + + (rtems_configuration_get_unified_work_area() ? 0 : overhead) + ); + + rtems_heap_set_sbrk_amount(sbrk_amount); + } + #endif + + /* + * The following may be helpful in debugging what goes wrong when + * you are allocating the Work Area in a new BSP. + */ + #ifdef BSP_GET_WORK_AREA_DEBUG + { + void *sp = __builtin_frame_address(0); + void *end = (char *) area.begin + area.size; + printk( + "work_area_start = 0x%p\n" + "work_area_size = %lu 0x%08lx\n" + "end = 0x%p\n" + "current stack pointer = 0x%p%s\n", + area.begin, + (unsigned long) area.size, /* decimal */ + (unsigned long) area.size, /* hexadecimal */ + end, + sp, + (uintptr_t) sp >= (uintptr_t) area.begin + && (uintptr_t) sp <= (uintptr_t) end ? + " OVERLAPS!" : "" + ); + } + #endif + + _Workspace_Handler_initialization(&area, 1, NULL); + + #ifdef BSP_GET_WORK_AREA_DEBUG + printk( + "heap_start = 0x%p\n" + "heap_size = %lu\n", + area.begin, + (unsigned long) area.size + ); + #endif + + RTEMS_Malloc_Initialize(&area, 1, NULL); +} + +static inline void bsp_work_area_initialize_with_table( + Heap_Area *areas, + size_t area_count +) +{ + _Workspace_Handler_initialization(areas, area_count, _Heap_Extend); + RTEMS_Malloc_Initialize(areas, area_count, _Heap_Extend); +} + +void bsp_work_area_initialize(void); + +/** + * @brief Standard start routine for secondary processors. + * + * This function is usually called by low-level startup code of secondary + * processors or boot loaders starting a secondary processor. The final step + * of this function is a call to + * _SMP_Start_multitasking_on_secondary_processor(). + */ +void bsp_start_on_secondary_processor(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_BOOTCARD_H */ diff --git a/bsps/include/bsp/bspVmeDmaList.h b/bsps/include/bsp/bspVmeDmaList.h new file mode 100644 index 0000000000..414afab5c9 --- /dev/null +++ b/bsps/include/bsp/bspVmeDmaList.h @@ -0,0 +1,140 @@ +/** + * @file + * + * @ingroup shared_bspvmedmalist + * + * @brief This header should only be used inside a BSP + * chosing to use bspVmeDmaList for implementing VMEDMA.h + */ + +#ifndef BSP_VME_DMA_LIST_H +#define BSP_VME_DMA_LIST_H + + + +/* + * The bspVmeDmaList utility implements part of the API defined by + * 'VMEDMA.h' namely all 'VMEDmaListDescriptor' related entry points: + * + * BSP_VMEDmaListDescriptorDestroy(), + * BSP_VMEDmaListDestroy(), + * BSP_VMEDmaListDescriptorEnq(), + * BSP_VMEDmaListDescriptorNext(), + * BSP_VMEDmaListDescriptorPrev(), + * BSP_VMEDmaListDescriptorSetUsr(), + * BSP_VMEDmaListDescriptorGetUsr(), + * BSP_VMEDmaListRefresh() + * + * Also, it provides helper routines to assist BSPs with implementing + * + * BSP_VMEDmaListDescriptorSetup() + * + * and + * + * BSP_VMEDmaListStart() + * + * by providing + * + * BSP_VMEDmaListDescriptorNewTool(), + * BSP_VMEDmaListDescriptorSetupTool(), + * + * and + * + * BSP_VMEDmaListDescriptorStartTool() + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2006, 2007 + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 <stdint.h> + +#include <bsp/VMEDMA.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct VMEDmaListNodeRec_ *VMEDmaListNode; + +typedef struct VMEDmaListClassRec_ *VMEDmaListClass; + +/** + * @defgroup shared_bspvmedmalist Create and setup a new descriptor. + * + * @ingroup shared_vmeuniverse + * + * @brief The BSP must supply the appropriate controller class. + */ + +VMEDmaListNode +BSP_VMEDmaListDescriptorNewTool( + VMEDmaListClass pc, + uint32_t attr_mask, + uint32_t xfer_mode, + uint32_t pci_addr, + uint32_t vme_addr, + uint32_t n_bytes); + +/* Setup an existing descriptor */ +VMEDmaListNode +BSP_VMEDmaListDescriptorSetupTool( + VMEDmaListNode n, + uint32_t attr_mask, + uint32_t xfer_mode, + uint32_t pci_addr, + uint32_t vme_addr, + uint32_t n_bytes); + + +/* Start a list DMA transfer on 'controller'. The 'controller' information + * must be provided by the BSP. + */ +int +BSP_VMEDmaListDescriptorStartTool(volatile void *controller, int channel, VMEDmaListNode n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/console-polled.h b/bsps/include/bsp/console-polled.h new file mode 100644 index 0000000000..09a99c30cb --- /dev/null +++ b/bsps/include/bsp/console-polled.h @@ -0,0 +1,43 @@ +/** + * @file + * + * @ingroup Console + * + * This file defines the interfaces between the single port + * polled console framework and the BSP. + */ + +/* + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef __BSP_CONSOLE_POLLED_h +#define __BSP_CONSOLE_POLLED_h + +/** + * This method polls the specified character @a ch to the specified + * console @a port. + * + * @param[in] port is the output port + * @param[in] ch is the character to print + */ +void console_outbyte_polled(int port, char ch); + +/** + * This method polls the specified @a port for an input character. + * console @a port. + * + * @param[in] port is the input port + * + * @return This method returns the character read of -1 if there is no data. + */ +int console_inbyte_nonblocking(int port); + +/** + * This method is invoked to initialize the console hardware device(s). + */ +void console_initialize_hardware(void); + +#endif diff --git a/bsps/include/bsp/console-termios.h b/bsps/include/bsp/console-termios.h new file mode 100644 index 0000000000..413dde4663 --- /dev/null +++ b/bsps/include/bsp/console-termios.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef BSP_CONSOLE_TERMIOS_H +#define BSP_CONSOLE_TERMIOS_H + +#include <rtems/termiostypes.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup ConsoleTermios Termios Console Driver + * + * @ingroup TermiostypesSupport + * + * @brief Console driver for Termios devices. + * + * In order to use this driver add the following lines to the Makefile.am of + * the BSP: + * + * @code + * libbsp_a_SOURCES += ../../shared/console-termios-init.c + * libbsp_a_SOURCES += ../../shared/console-termios.c + * libbsp_a_SOURCES += console/console-config.c + * @endcode + * + * Define the console_device_table and console_device_count in the + * console-config.c file of the BSP. + * + * @{ + */ + +/** + * @brief Console device probe function type. + * + * @param[in] context The Termios device context. + * + * @retval true Install this device. + * @retval false Otherwise. + */ +typedef bool (*console_device_probe)(rtems_termios_device_context *context); + +/** + * @brief Console device information. + */ +typedef struct { + /** + * @brief The device file path. + * + * The "/dev/console" device will be automatically installed as the first + * device of console_device_table with a successful probe. + */ + const char *device_file; + + /** + * @brief The device probe function. + */ + console_device_probe probe; + + /** + * @brief The Termios device handler. + */ + const rtems_termios_device_handler *handler; + + /** + * @brief The Termios device flow control handler. + */ + const rtems_termios_device_flow *flow; + + /** + * @brief The Termios device context. + */ + rtems_termios_device_context *context; +} console_device; + +/** + * @brief Returns true and does nothing else. + */ +bool console_device_probe_default(rtems_termios_device_context *context); + +/** + * @brief Table for console devices installed via console_initialize() during + * system initialization. + * + * It must be provided by the BSP. + * + * @see console_device_count. + */ +extern const console_device console_device_table[]; + +/** + * @brief Count of entries in the console_device_table. + * + * It must be provided by the BSP. + */ +extern const size_t console_device_count; + +/** @{ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* BSP_CONSOLE_TERMIOS_H */ diff --git a/bsps/include/bsp/default-initial-extension.h b/bsps/include/bsp/default-initial-extension.h new file mode 100644 index 0000000000..1c795b7278 --- /dev/null +++ b/bsps/include/bsp/default-initial-extension.h @@ -0,0 +1,53 @@ +/** + * @file + * + * @ingroup shared_defaultinitialextension + * + * @brief DEFAULT_INITIAL_EXTENSION Support + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_DEFAULT_INITIAL_EXTENSION_H +#define LIBBSP_SHARED_DEFAULT_INITIAL_EXTENSION_H + +#include <rtems.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup shared_defaultinitialextension DEFAULT_INITIAL_EXTENSION Support + * + * @ingroup shared_include + * + * @brief DEFAULT_INITIAL_EXTENSION Support Package + */ + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +); + +#define BSP_INITIAL_EXTENSION \ + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, bsp_fatal_extension, NULL } + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_DEFAULT_INITIAL_EXTENSION_H */ diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h new file mode 100644 index 0000000000..ca2e39aba8 --- /dev/null +++ b/bsps/include/bsp/fatal.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2012, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_BSP_FATAL_H +#define LIBBSP_SHARED_BSP_FATAL_H + +#include <rtems.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define BSP_FATAL_CODE_BLOCK(idx) ((unsigned long) (idx) * 256UL) + +/** + * @brief BSP fatal error codes. + */ +typedef enum { + /* Generic BSP fatal codes */ + BSP_FATAL_INTERRUPT_INITIALIZATION = BSP_FATAL_CODE_BLOCK(0), + BSP_FATAL_SPURIOUS_INTERRUPT, + BSP_FATAL_CONSOLE_MULTI_INIT, + BSP_FATAL_CONSOLE_NO_MEMORY_0, + BSP_FATAL_CONSOLE_NO_MEMORY_1, + BSP_FATAL_CONSOLE_NO_MEMORY_2, + BSP_FATAL_CONSOLE_NO_MEMORY_3, + BSP_FATAL_CONSOLE_REGISTER_DEV_0, + BSP_FATAL_CONSOLE_REGISTER_DEV_1, + BSP_FATAL_CONSOLE_NO_DEV, + BSP_FATAL_CONSOLE_INSTALL_0, + BSP_FATAL_CONSOLE_INSTALL_1, + BSP_FATAL_CONSOLE_REGISTER_DEV_2, + + /* ARM fatal codes */ + BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(1), + BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_REMOVE, + BSP_ARM_PL111_FATAL_REGISTER_DEV, + BSP_ARM_PL111_FATAL_SEM_CREATE, + BSP_ARM_PL111_FATAL_SEM_RELEASE, + BSP_ARM_A9MPCORE_FATAL_CLOCK_SMP_INIT, + BSP_ARM_ARMV7M_CPU_COUNTER_INIT, + BSP_ARM_FATAL_GENERIC_TIMER_CLOCK_IRQ_INSTALL, + + /* LEON3 fatal codes */ + LEON3_FATAL_NO_IRQMP_CONTROLLER = BSP_FATAL_CODE_BLOCK(2), + LEON3_FATAL_CONSOLE_REGISTER_DEV, + LEON3_FATAL_CLOCK_INITIALIZATION, + LEON3_FATAL_INVALID_CACHE_CONFIG_MAIN_PROCESSOR, + LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR, + LEON3_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT, + + /* LPC24XX fatal codes */ + LPC24XX_FATAL_PL111_SET_UP = BSP_FATAL_CODE_BLOCK(3), + LPC24XX_FATAL_PL111_PINS_SET_UP, + LPC24XX_FATAL_PL111_PINS_TEAR_DOWN, + LPC24XX_FATAL_PL111_TEAR_DOWN, + + /* MPC5200 fatal codes */ + MPC5200_FATAL_PCF8563_INVALID_YEAR = BSP_FATAL_CODE_BLOCK(4), + MPC5200_FATAL_SLICETIMER_0_IRQ_INSTALL, + MPC5200_FATAL_SLICETIMER_1_IRQ_INSTALL, + MPC5200_FATAL_TM27_IRQ_INSTALL, + MPC5200_FATAL_MSCAN_A_INIT, + MPC5200_FATAL_MSCAN_B_INIT, + MPC5200_FATAL_MSCAN_A_SET_MODE, + MPC5200_FATAL_MSCAN_B_SET_MODE, + MPC5200_FATAL_ATA_DISK_IO_INIT, + MPC5200_FATAL_ATA_DISK_CREATE, + MPC5200_FATAL_ATA_DMA_SINGLE_IRQ_INSTALL, + MPC5200_FATAL_ATA_LOCK_CREATE, + MPC5200_FATAL_ATA_LOCK_DESTROY, + + /* MPC55XX fatal codes */ + MPC55XX_FATAL_FMPLL_LOCK = BSP_FATAL_CODE_BLOCK(5), + MPC55XX_FATAL_CLOCK_EMIOS_IRQ_INSTALL, + MPC55XX_FATAL_CLOCK_EMIOS_PRESCALER, + MPC55XX_FATAL_CLOCK_EMIOS_INTERVAL, + MPC55XX_FATAL_CLOCK_PIT_IRQ_INSTALL, + MPC55XX_FATAL_CONSOLE_GENERIC_COUNT, + MPC55XX_FATAL_CONSOLE_GENERIC_REGISTER, + MPC55XX_FATAL_CONSOLE_GENERIC_REGISTER_CONSOLE, + MPC55XX_FATAL_CONSOLE_ESCI_BAUD, + MPC55XX_FATAL_CONSOLE_ESCI_ATTRIBUTES, + MPC55XX_FATAL_CONSOLE_ESCI_IRQ_INSTALL, + MPC55XX_FATAL_CONSOLE_LINFLEX_BAUD, + MPC55XX_FATAL_CONSOLE_LINFLEX_ATTRIBUTES, + MPC55XX_FATAL_CONSOLE_LINFLEX_RX_IRQ_INSTALL, + MPC55XX_FATAL_CONSOLE_LINFLEX_TX_IRQ_INSTALL, + MPC55XX_FATAL_CONSOLE_LINFLEX_ERR_IRQ_INSTALL, + MPC55XX_FATAL_CONSOLE_LINFLEX_RX_IRQ_REMOVE, + MPC55XX_FATAL_CONSOLE_LINFLEX_TX_IRQ_REMOVE, + MPC55XX_FATAL_CONSOLE_LINFLEX_ERR_IRQ_REMOVE, + MPC55XX_FATAL_EDMA_IRQ_INSTALL, + MPC55XX_FATAL_EDMA_IRQ_REMOVE, + + /* MRM332 fatal codes */ + MRM332_FATAL_SPURIOUS_INTERRUPT = BSP_FATAL_CODE_BLOCK(6), + + /* PowerPC fatal codes */ + PPC_FATAL_EXCEPTION_INITIALIZATION = BSP_FATAL_CODE_BLOCK(7), + + /* Libchip fatal codes */ + DWMAC_FATAL_TOO_MANY_RBUFS_CONFIGURED = BSP_FATAL_CODE_BLOCK(8), + + /* ARM fatal codes */ + ARM_FATAL_L2C_310_UNEXPECTED_ID = BSP_FATAL_CODE_BLOCK(9), + ARM_FATAL_L2C_310_UNEXPECTED_NUM_WAYS, + ARM_FATAL_L2C_310_EXCLUSIVE_CONFIG, + + /* QorIQ fatal codes */ + QORIQ_FATAL_SMP_IPI_HANDLER_INSTALL = BSP_FATAL_CODE_BLOCK(10), + QORIQ_FATAL_FDT_NO_BUS_FREQUENCY, + QORIQ_FATAL_FDT_NO_CLOCK_FREQUENCY, + QORIQ_FATAL_FDT_NO_TIMEBASE_FREQUENCY, + QORIQ_FATAL_RESTART_FAILED, + QORIQ_FATAL_RESTART_INSTALL_INTERRUPT, + QORIQ_FATAL_RESTART_INTERRUPT_FAILED, + + /* ATSAM fatal codes */ + ATSAM_FATAL_XDMA_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(11), + ATSAM_FATAL_PIO_IRQ_A, + ATSAM_FATAL_PIO_IRQ_B, + ATSAM_FATAL_PIO_IRQ_C, + ATSAM_FATAL_PIO_IRQ_D, + ATSAM_FATAL_PIO_IRQ_E, + ATSAM_FATAL_PIO_CONFIGURE_IT, + + /* i.MX fatal codes */ + IMX_FATAL_GENERIC_TIMER_FREQUENCY = BSP_FATAL_CODE_BLOCK(12) +} bsp_fatal_code; + +RTEMS_NO_RETURN static inline void +bsp_fatal( bsp_fatal_code code ) +{ + rtems_fatal( RTEMS_FATAL_SOURCE_BSP, (rtems_fatal_code) code ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_BSP_FATAL_H */ diff --git a/bsps/include/bsp/fdt.h b/bsps/include/bsp/fdt.h new file mode 100644 index 0000000000..4ed05b136c --- /dev/null +++ b/bsps/include/bsp/fdt.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_FDT_H +#define LIBBSP_SHARED_FDT_H + +#include <bsp.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * BSPs that implement the FDT support functions must define + * BSP_FDT_IS_SUPPORTED. + */ + +/** + * @brief Copies the specified source FDT to a dedicated global data area. + * + * The source FDT is usually provided by a bootloader and may be located in a + * memory area that is used by the program. The low-level initialization + * should copy the FDT for later use. + * + * The copy can be accessed by bsp_fdt_get(). + * + * @param[in] src The source FDT. + */ +void bsp_fdt_copy(const void *src); + +/** + * @brief Returns the FDT of the BSP. + * + * @return The FDT of the BSP. + */ +const void *bsp_fdt_get(void); + +/** + * @brief Maps the interrupt number of the FDT to the interrupt vector used by + * the interrupt management. + * + * This function is used by the libbsd to implement the OFW_BUS_MAP_INTR bus + * method. + * + * @param[in] intr The FDT interrupt number cells. + * @param[in] icells The FDT interrupt cell count. + * + * @return The interrupt vector of the FDT interrupt number. + */ +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_FDT_H */ diff --git a/bsps/include/bsp/gpio.h b/bsps/include/bsp/gpio.h new file mode 100644 index 0000000000..64a877ae7a --- /dev/null +++ b/bsps/include/bsp/gpio.h @@ -0,0 +1,955 @@ +/** + * @file gpio.h + * + * @ingroup rtems_gpio + * + * @brief RTEMS GPIO API definition. + */ + +/* + * Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_GPIO_H +#define LIBBSP_SHARED_GPIO_H + +#include <bsp.h> +#include <rtems.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !defined(BSP_GPIO_PIN_COUNT) || !defined(BSP_GPIO_PINS_PER_BANK) + #error "BSP_GPIO_PIN_COUNT or BSP_GPIO_PINS_PER_BANK is not defined." +#endif + +#if BSP_GPIO_PIN_COUNT <= 0 || BSP_GPIO_PINS_PER_BANK <= 0 + #error "Invalid BSP_GPIO_PIN_COUNT or BSP_GPIO_PINS_PER_BANK." +#endif + +#if BSP_GPIO_PINS_PER_BANK > 32 + #error "Invalid BSP_GPIO_PINS_PER_BANK. Must be in the range of 1 to 32." +#endif + +#define GPIO_LAST_BANK_PINS BSP_GPIO_PIN_COUNT % BSP_GPIO_PINS_PER_BANK + +#if GPIO_LAST_BANK_PINS > 0 + #define GPIO_BANK_COUNT (BSP_GPIO_PIN_COUNT / BSP_GPIO_PINS_PER_BANK) + 1 +#else + #define GPIO_BANK_COUNT BSP_GPIO_PIN_COUNT / BSP_GPIO_PINS_PER_BANK + #undef GPIO_LAST_BANK_PINS + #define GPIO_LAST_BANK_PINS BSP_GPIO_PINS_PER_BANK +#endif + +#if defined(BSP_GPIO_PINS_PER_SELECT_BANK) && BSP_GPIO_PINS_PER_SELECT_BANK > 32 + #error "Invalid BSP_GPIO_PINS_PER_SELECT_BANK. Must under and including 32." +#elif defined(BSP_GPIO_PINS_PER_SELECT_BANK) <= 32 + #define GPIO_SELECT_BANK_COUNT \ + BSP_GPIO_PINS_PER_BANK / BSP_GPIO_PINS_PER_SELECT_BANK +#endif + +#define INTERRUPT_SERVER_PRIORITY 1 +#define INTERRUPT_SERVER_STACK_SIZE 2 * RTEMS_MINIMUM_STACK_SIZE +#define INTERRUPT_SERVER_MODES RTEMS_TIMESLICE | RTEMS_PREEMPT +#define INTERRUPT_SERVER_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES + +#define GPIO_INPUT_ERROR ~0 + +/** + * @name GPIO data structures + * + * @{ + */ + +/** + * @brief The set of possible configurations for a GPIO pull-up resistor. + * + * Enumerated type to define the possible pull-up resistor configurations + * for a GPIO pin. + */ +typedef enum +{ + PULL_UP = 1, + PULL_DOWN, + NO_PULL_RESISTOR +} rtems_gpio_pull_mode; + +/** + * @brief The set of possible functions a pin can have. + * + * Enumerated type to define a pin function. + */ +typedef enum +{ + DIGITAL_INPUT = 0, + DIGITAL_OUTPUT, + BSP_SPECIFIC, + NOT_USED +} rtems_gpio_function; + +/** + * @brief The set of possible interrupts a GPIO pin can generate. + * + * Enumerated type to define a GPIO pin interrupt. + */ +typedef enum +{ + FALLING_EDGE = 0, + RISING_EDGE, + LOW_LEVEL, + HIGH_LEVEL, + BOTH_EDGES, + BOTH_LEVELS, + NONE +} rtems_gpio_interrupt; + +/** + * @brief The set of possible handled states an user-defined interrupt + * handler can return. + * + * Enumerated type to define an interrupt handler handled state. + */ +typedef enum +{ + IRQ_HANDLED, + IRQ_NONE +} rtems_gpio_irq_state; + +/** + * @brief The set of flags to specify an user-defined interrupt handler + * uniqueness on a GPIO pin. + * + * Enumerated type to define an interrupt handler shared flag. + */ +typedef enum +{ + SHARED_HANDLER, + UNIQUE_HANDLER +} rtems_gpio_handler_flag; + +/** + * @brief Object containing relevant information for assigning a BSP specific + * function to a pin. + * + * Encapsulates relevant data for a BSP specific GPIO function. + */ +typedef struct +{ + /* The BSP defined function code. */ + uint32_t io_function; + + void *pin_data; +} rtems_gpio_specific_data; + +/** + * @brief Object containing configuration information + * regarding interrupts. + */ +typedef struct +{ + rtems_gpio_interrupt active_interrupt; + + rtems_gpio_handler_flag handler_flag; + + bool threaded_interrupts; + + /* Interrupt handler function. */ + rtems_gpio_irq_state (*handler) (void *arg); + + /* Interrupt handler function arguments. */ + void *arg; + + /* Software switch debounce settings. It should contain the amount of clock + * ticks that must pass between interrupts to ensure that the interrupt + * was not caused by a switch bounce. + * If set to 0 this feature is disabled . */ + uint32_t debounce_clock_tick_interval; +} rtems_gpio_interrupt_configuration; + +/** + * @brief Object containing configuration information + * to request/update a GPIO pin. + */ +typedef struct +{ + /* Processor pin number. */ + uint32_t pin_number; + rtems_gpio_function function; + + /* Pull resistor setting. */ + rtems_gpio_pull_mode pull_mode; + + /* If digital out pin, set to TRUE to set the pin to logical high, + * or FALSE for logical low. If not a digital out then this + * is ignored. */ + bool output_enabled; + + /* If true inverts digital in/out applicational logic. */ + bool logic_invert; + + /* Pin interrupt configuration. Should be NULL if not used. */ + rtems_gpio_interrupt_configuration *interrupt; + + /* Structure with BSP specific data, to use during the pin request. + * If function == BSP_SPECIFIC this should have a pointer to + * a rtems_gpio_specific_data structure. + * + * If not this field may be NULL. This is passed to the BSP function + * so any BSP specific data can be passed to it through this pointer. */ + void *bsp_specific; +} rtems_gpio_pin_conf; + +/** + * @brief Object containing configuration information + * to assign GPIO functions to multiple pins + * at the same time. To be used by BSP code only. + */ +typedef struct +{ + /* Global GPIO pin number. */ + uint32_t pin_number; + + /* RTEMS GPIO pin function code. */ + rtems_gpio_function function; + + /* BSP specific function code. Only used if function == BSP_SPECIFIC */ + uint32_t io_function; + + /* BSP specific data. */ + void *bsp_specific; +} rtems_gpio_multiple_pin_select; + +/** + * @brief Object containing configuration information + * to request a GPIO pin group. + */ +typedef struct +{ + const rtems_gpio_pin_conf *digital_inputs; + uint32_t input_count; + + const rtems_gpio_pin_conf *digital_outputs; + uint32_t output_count; + + const rtems_gpio_pin_conf *bsp_specifics; + uint32_t bsp_specific_pin_count; +} rtems_gpio_group_definition; + +/** + * @brief Opaque type for a GPIO pin group. + */ +typedef struct rtems_gpio_group rtems_gpio_group; + +/** @} */ + +/** + * @name gpio Usage + * + * @{ + */ + +/** + * @brief Initializes the GPIO API. + * + * @retval RTEMS_SUCCESSFUL API successfully initialized. + * @retval * @see rtems_semaphore_create(). + */ +extern rtems_status_code rtems_gpio_initialize(void); + +/** + * @brief Instantiates a GPIO pin group. + * To define the group @see rtems_gpio_define_pin_group(). + * + * @retval rtems_gpio_group pointer. + */ +extern rtems_gpio_group *rtems_gpio_create_pin_group(void); + +/** + * @brief Requests a GPIO pin group configuration. + * + * @param[in] group_definition rtems_gpio_group_definition structure filled with + * the group pins configurations. + * @param[out] group Reference to the created group. + * + * @retval RTEMS_SUCCESSFUL Pin group was configured successfully. + * @retval RTEMS_UNSATISFIED @var group_definition or @var group is NULL, + * the @var pins are not from the same bank, + * no pins were defined or could not satisfy at + * least one given configuration. + * @retval RTEMS_RESOURCE_IN_USE At least one pin is already being used. + * @retval * @see rtems_semaphore_create(). + */ +extern rtems_status_code rtems_gpio_define_pin_group( + const rtems_gpio_group_definition *group_definition, + rtems_gpio_group *group +); + +/** + * @brief Writes a value to the group's digital outputs. The pins order + * is as defined in the group definition. + * + * @param[in] data Data to write/send. + * @param[in] group Reference to the group. + * + * @retval RTEMS_SUCCESSFUL Data successfully written. + * @retval RTEMS_NOT_DEFINED Group has no output pins. + * @retval RTEMS_UNSATISFIED Could not operate on at least one of the pins. + */ +extern rtems_status_code rtems_gpio_write_group( + uint32_t data, + rtems_gpio_group *group +); + +/** + * @brief Reads the value/level of the group's digital inputs. The pins order + * is as defined in the group definition. + * + * @param[in] group Reference to the group. + * + * @retval The function returns a 32-bit bitmask with the group's input pins + * current logical values. + * @retval GPIO_INPUT_ERROR Group has no input pins. + */ +extern uint32_t rtems_gpio_read_group(rtems_gpio_group *group); + +/** + * @brief Performs a BSP specific operation on a group of pins. The pins order + * is as defined in the group definition. + * + * @param[in] group Reference to the group. + * @param[in] arg Pointer to a BSP defined structure with BSP-specific + * data. This field is handled by the BSP. + * + * @retval RTEMS_SUCCESSFUL Operation completed with success. + * @retval RTEMS_NOT_DEFINED Group has no BSP specific pins, or the BSP does not + * support BSP specific operations for groups. + * @retval RTEMS_UNSATISFIED Could not operate on at least one of the pins. + */ +extern rtems_status_code rtems_gpio_group_bsp_specific_operation( + rtems_gpio_group *group, + void *arg +); + +/** + * @brief Requests a GPIO pin configuration. + * + * @param[in] conf rtems_gpio_pin_conf structure filled with the pin information + * and desired configurations. + * + * @retval RTEMS_SUCCESSFUL Pin was configured successfully. + * @retval RTEMS_UNSATISFIED Could not satisfy the given configuration. + */ +extern rtems_status_code rtems_gpio_request_configuration( + const rtems_gpio_pin_conf *conf +); + +/** + * @brief Updates the current configuration of a GPIO pin . + * + * @param[in] conf rtems_gpio_pin_conf structure filled with the pin information + * and desired configurations. + * + * @retval RTEMS_SUCCESSFUL Pin configuration was updated successfully. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED The pin is not being used. + * @retval RTEMS_UNSATISFIED Could not update the pin's configuration. + */ +extern rtems_status_code rtems_gpio_update_configuration( + const rtems_gpio_pin_conf *conf +); + +/** + * @brief Sets multiple output GPIO pins with the logical high. + * + * @param[in] pin_numbers Array with the GPIO pin numbers to set. + * @param[in] count Number of GPIO pins to set. + * + * @retval RTEMS_SUCCESSFUL All pins were set successfully. + * @retval RTEMS_INVALID_ID At least one pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED At least one of the received pins + * is not configured as a digital output. + * @retval RTEMS_UNSATISFIED Could not set the GPIO pins. + */ +extern rtems_status_code rtems_gpio_multi_set( + uint32_t *pin_numbers, + uint32_t pin_count +); + +/** + * @brief Sets multiple output GPIO pins with the logical low. + * + * @param[in] pin_numbers Array with the GPIO pin numbers to clear. + * @param[in] count Number of GPIO pins to clear. + * + * @retval RTEMS_SUCCESSFUL All pins were cleared successfully. + * @retval RTEMS_INVALID_ID At least one pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED At least one of the received pins + * is not configured as a digital output. + * @retval RTEMS_UNSATISFIED Could not clear the GPIO pins. + */ +extern rtems_status_code rtems_gpio_multi_clear( + uint32_t *pin_numbers, + uint32_t pin_count +); + +/** + * @brief Returns the value (level) of multiple GPIO input pins. + * + * @param[in] pin_numbers Array with the GPIO pin numbers to read. + * @param[in] count Number of GPIO pins to read. + * + * @retval Bitmask with the values of the corresponding pins. + * 0 for logical low and 1 for logical high. + * @retval GPIO_INPUT_ERROR Could not read at least one pin level. + */ +extern uint32_t rtems_gpio_multi_read( + uint32_t *pin_numbers, + uint32_t pin_count +); + +/** + * @brief Sets an output GPIO pin with the logical high. + * + * @param[in] pin_number GPIO pin number. + * + * @retval RTEMS_SUCCESSFUL Pin was set successfully. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED The received pin is not configured + * as a digital output. + * @retval RTEMS_UNSATISFIED Could not set the GPIO pin. + */ +extern rtems_status_code rtems_gpio_set(uint32_t pin_number); + +/** + * @brief Sets an output GPIO pin with the logical low. + * + * @param[in] pin_number GPIO pin number. + * + * @retval RTEMS_SUCCESSFUL Pin was cleared successfully. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED The received pin is not configured + * as a digital output. + * @retval RTEMS_UNSATISFIED Could not clear the GPIO pin. + */ +extern rtems_status_code rtems_gpio_clear(uint32_t pin_number); + +/** + * @brief Returns the value (level) of a GPIO input pin. + * + * @param[in] pin_number GPIO pin number. + * + * @retval The function returns 0 or 1 depending on the pin current + * logical value. + * @retval -1 Pin number is invalid, or not a digital input pin. + */ +extern int rtems_gpio_get_value(uint32_t pin_number); + +/** + * @brief Requests multiple GPIO pin configurations. If the BSP provides + * support for parallel selection each call to this function will + * result in a single call to the GPIO hardware, else each pin + * configuration will be done in individual and sequential calls. + * All pins must belong to the same GPIO bank. + * + * @param[in] pins Array of rtems_gpio_pin_conf structures filled with the pins + * information and desired configurations. All pins must belong + * to the same GPIO bank. + * @param[in] pin_count Number of pin configurations in the @var pins array. + * + * @retval RTEMS_SUCCESSFUL All pins were configured successfully. + * @retval RTEMS_INVALID_ID At least one pin number in the @var pins array + * is invalid. + * @retval RTEMS_RESOURCE_IN_USE At least one pin is already being used. + * @retval RTEMS_UNSATISFIED Could not satisfy at least one given configuration. + */ +extern rtems_status_code rtems_gpio_multi_select( + const rtems_gpio_pin_conf *pins, + uint8_t pin_count +); + +/** + * @brief Assigns a certain function to a GPIO pin. + * + * @param[in] pin_number GPIO pin number. + * @param[in] function The new function for the pin. + * @param[in] output_enabled If TRUE and @var function is DIGITAL_OUTPUT, + * then the pin is set with the logical high. + * Otherwise it is set with logical low. + * @param[in] logic_invert Reverses the digital I/O logic for DIGITAL_INPUT + * and DIGITAL_OUTPUT pins. + * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific + * data. This field is handled by the BSP. + * + * @retval RTEMS_SUCCESSFUL Pin was configured successfully. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_RESOURCE_IN_USE The received pin is already being used. + * @retval RTEMS_UNSATISFIED Could not assign the GPIO function. + * @retval RTEMS_NOT_DEFINED GPIO function not defined, or NOT_USED. + */ +extern rtems_status_code rtems_gpio_request_pin( + uint32_t pin_number, + rtems_gpio_function function, + bool output_enable, + bool logic_invert, + void *bsp_specific +); + +/** + * @brief Configures a single GPIO pin pull resistor. + * + * @param[in] pin_number GPIO pin number. + * @param[in] mode The pull resistor mode. + * + * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_UNSATISFIED Could not set the pull mode. + */ +extern rtems_status_code rtems_gpio_resistor_mode( + uint32_t pin_number, + rtems_gpio_pull_mode mode +); + +/** + * @brief Releases a GPIO pin, making it available to be used again. + * + * @param[in] pin_number GPIO pin number. + * + * @retval RTEMS_SUCCESSFUL Pin successfully disabled. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval * Could not disable an active interrupt on this pin, + * @see rtems_gpio_disable_interrupt(). + */ +extern rtems_status_code rtems_gpio_release_pin(uint32_t pin_number); + +/** + * @brief Releases a GPIO pin, making it available to be used again. + * + * @param[in] conf GPIO pin configuration to be released. + * + * @retval RTEMS_SUCCESSFUL Pin successfully disabled. + * @retval RTEMS_UNSATISFIED Pin configuration is NULL. + * @retval * @see rtems_gpio_release_pin(). + */ +extern rtems_status_code rtems_gpio_release_configuration( + const rtems_gpio_pin_conf *conf +); + +/** + * @brief Releases multiple GPIO pins, making them available to be used again. + * + * @param[in] pins Array of rtems_gpio_pin_conf structures. + * @param[in] pin_count Number of pin configurations in the @var pins array. + * + * @retval RTEMS_SUCCESSFUL Pins successfully disabled. + * @retval RTEMS_UNSATISFIED @var pins array is NULL. + * @retval * @see rtems_gpio_release_pin(). + */ +extern rtems_status_code rtems_gpio_release_multiple_pins( + const rtems_gpio_pin_conf *pins, + uint32_t pin_count +); + +/** + * @brief Releases a GPIO pin group, making the pins used available to be + * repurposed. + * + * @param[in] conf GPIO pin configuration to be released. + * + * @retval RTEMS_SUCCESSFUL Pins successfully disabled. + * @retval * @see rtems_gpio_release_pin(), @see rtems_semaphore_delete() or + * @see rtems_semaphore_flush(). + */ +extern rtems_status_code rtems_gpio_release_pin_group( + rtems_gpio_group *group +); + +/** + * @brief Attaches a debouncing function to a given pin/switch. + * Debouncing is done by requiring a certain number of clock ticks to + * pass between interrupts. Any interrupt fired too close to the last + * will be ignored as it is probably the result of an involuntary + * switch/button bounce after being released. + * + * @param[in] pin_number GPIO pin number. + * @param[in] ticks Minimum number of clock ticks that must pass between + * interrupts so it can be considered a legitimate + * interrupt. + * + * @retval RTEMS_SUCCESSFUL Debounce function successfully attached to the pin. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED The current pin is not configured as a digital + * input, hence it can not be connected to a switch, + * or interrupts are not enabled for this pin. + */ +extern rtems_status_code rtems_gpio_debounce_switch( + uint32_t pin_number, + int ticks +); + +/** + * @brief Connects a new user-defined interrupt handler to a given pin. + * + * @param[in] pin_number GPIO pin number. + * @param[in] handler Pointer to a function that will be called every time + * the enabled interrupt for the given pin is generated. + * This function must return information about its + * handled/unhandled state. + * @param[in] arg Void pointer to the arguments of the user-defined handler. + * + * @retval RTEMS_SUCCESSFUL Handler successfully connected to this pin. + * @retval RTEMS_NO_MEMORY Could not connect more user-defined handlers to + * the given pin. + * @retval RTEMS_NOT_CONFIGURED The given pin has no interrupt configured. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_TOO_MANY The pin's current handler is set as unique. + * @retval RTEMS_RESOURCE_IN_USE The current user-defined handler for this pin + * is unique. + */ +extern rtems_status_code rtems_gpio_interrupt_handler_install( + uint32_t pin_number, + rtems_gpio_irq_state (*handler) (void *arg), + void *arg +); + +/** + * @brief Enables interrupts to be generated on a given GPIO pin. + * When fired that interrupt will call the given handler. + * + * @param[in] pin_number GPIO pin number. + * @param[in] interrupt Type of interrupt to enable for the pin. + * @param[in] flag Defines the uniqueness of the interrupt handler for the pin. + * @param[in] threaded_handling Defines if the handler should be called from a + * thread/task or from normal ISR contex. + * @param[in] handler Pointer to a function that will be called every time + * @var interrupt is generated. This function must return + * information about its handled/unhandled state. + * @param[in] arg Void pointer to the arguments of the user-defined handler. + * + * @retval RTEMS_SUCCESSFUL Interrupt successfully enabled for this pin. + * @retval RTEMS_UNSATISFIED Could not install the GPIO ISR, create/start + * the handler task, or enable the interrupt + * on the pin. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED The received pin is not configured + * as a digital input, the pin is on a + * pin grouping. + * @retval RTEMS_RESOURCE_IN_USE The pin already has an enabled interrupt, + * or the handler threading policy does not match + * the bank's policy. + * @retval RTEMS_NO_MEMORY Could not store the pin's interrupt configuration. + */ +extern rtems_status_code rtems_gpio_enable_interrupt( + uint32_t pin_number, + rtems_gpio_interrupt interrupt, + rtems_gpio_handler_flag flag, + bool threaded_handling, + rtems_gpio_irq_state (*handler) (void *arg), + void *arg +); + +/** + * @brief Disconnects an user-defined interrupt handler from the given pin. + * If in the end there are no more user-defined handlers connected + * to the pin, interrupts are disabled on the given pin. + * + * @param[in] pin_number GPIO pin number. + * @param[in] handler Pointer to the user-defined handler + * @param[in] arg Void pointer to the arguments of the user-defined handler. + * + * @retval RTEMS_SUCCESSFUL Handler successfully disconnected from this pin. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED Pin has no active interrupts. + * @retval * @see rtems_gpio_disable_interrupt() + */ +extern rtems_status_code rtems_gpio_interrupt_handler_remove( + uint32_t pin_number, + rtems_gpio_irq_state (*handler) (void *arg), + void *arg +); + +/** + * @brief Stops interrupts from being generated on a given GPIO pin + * and removes the corresponding handler. + * + * @param[in] pin_number GPIO pin number. + * + * @retval RTEMS_SUCCESSFUL Interrupt successfully disabled for this pin. + * @retval RTEMS_INVALID_ID Pin number is invalid. + * @retval RTEMS_NOT_CONFIGURED Pin has no active interrupts. + * @retval RTEMS_UNSATISFIED Could not remove the current interrupt handler, + * could not recognize the current active interrupt + * on this pin or could not disable interrupts on + * this pin. + */ +extern rtems_status_code rtems_gpio_disable_interrupt(uint32_t pin_number); + +/** + * @brief Sets multiple output GPIO pins with the logical high. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] bitmask Bitmask of GPIO pins to set in the given bank. + * + * @retval RTEMS_SUCCESSFUL All pins were set successfully. + * @retval RTEMS_UNSATISFIED Could not set at least one of the pins. + */ +extern rtems_status_code rtems_gpio_bsp_multi_set( + uint32_t bank, + uint32_t bitmask +); + +/** + * @brief Sets multiple output GPIO pins with the logical low. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] bitmask Bitmask of GPIO pins to clear in the given bank. + * + * @retval RTEMS_SUCCESSFUL All pins were cleared successfully. + * @retval RTEMS_UNSATISFIED Could not clear at least one of the pins. + */ +extern rtems_status_code rtems_gpio_bsp_multi_clear( + uint32_t bank, + uint32_t bitmask +); + +/** + * @brief Returns the value (level) of multiple GPIO input pins. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] bitmask Bitmask of GPIO pins to read in the given bank. + * + * @retval The function must return a bitmask with the values of the + * corresponding pins. 0 for logical low and 1 for logical high. + * @retval GPIO_INPUT_ERROR Could not read at least one pin level. + */ +extern uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask); + +/** + * @brief Performs a BSP specific operation on a group of pins. + * The implementation for this function may be omitted if the target + * does not support the feature, by returning RTEMS_NOT_DEFINED. + * + * @param[in] bank GPIO bank number. + * @param[in] pins Array filled with BSP specific pin numbers. All pins belong + * to the same select bank. + * @param[in] pin_count Number of pin configurations in the @var pins array. + * @param[in] arg Pointer to a BSP defined structure with BSP-specific + * data. This field is handled by the BSP. + * + * @retval RTEMS_SUCCESSFUL Operation completed with success. + * @retval RTEMS_NOT_DEFINED Group has no BSP specific pins, or the BSP does not + * support BSP specific operations for groups. + * @retval RTEMS_UNSATISFIED Could not operate on at least one of the pins. + */ +extern rtems_status_code rtems_gpio_bsp_specific_group_operation( + uint32_t bank, + uint32_t *pins, + uint32_t pin_count, + void *arg +); + +/** + * @brief Assigns GPIO functions to all the given pins in a single register + * operation. + * The implementation for this function may be omitted if the target + * does not support the feature, by returning RTEMS_NOT_DEFINED. + * + * @param[in] pins Array of rtems_gpio_multiple_pin_select structures filled + * with the pins desired functions. All pins belong to the + * same select bank. + * @param[in] pin_count Number of pin configurations in the @var pins array. + * @param[in] select_bank Select bank number of the received pins. + * + * @retval RTEMS_SUCCESSFUL Functions were assigned successfully. + * @retval RTEMS_NOT_DEFINED The BSP does not support multiple pin function + * assignment. + * @retval RTEMS_UNSATISFIED Could not assign the functions to the pins. + */ +extern rtems_status_code rtems_gpio_bsp_multi_select( + rtems_gpio_multiple_pin_select *pins, + uint32_t pin_count, + uint32_t select_bank +); + +/** + * @brief Sets an output GPIO pin with the logical high. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * + * @retval RTEMS_SUCCESSFUL Pin was set successfully. + * @retval RTEMS_UNSATISFIED Could not set the given pin. + */ +extern rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin); + +/** + * @brief Sets an output GPIO pin with the logical low. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * + * @retval RTEMS_SUCCESSFUL Pin was cleared successfully. + * @retval RTEMS_UNSATISFIED Could not clear the given pin. + */ +extern rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin); + +/** + * @brief Returns the value (level) of a GPIO input pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * + * @retval The function must return 0 if the pin level is a logical low, + * or non zero if it has a logical high. + * @retval GPIO_INPUT_ERROR Could not read the pin level. + */ +extern uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin); + +/** + * @brief Assigns the digital input function to the given pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific + * data. + * + * @retval RTEMS_SUCCESSFUL Function was assigned successfully. + * @retval RTEMS_UNSATISFIED Could not assign the function to the pin. + */ +extern rtems_status_code rtems_gpio_bsp_select_input( + uint32_t bank, + uint32_t pin, + void *bsp_specific +); + +/** + * @brief Assigns the digital output function to the given pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific + * data. + * + * @retval RTEMS_SUCCESSFUL Function was assigned successfully. + * @retval RTEMS_UNSATISFIED Could not assign the function to the pin. + */ +extern rtems_status_code rtems_gpio_bsp_select_output( + uint32_t bank, + uint32_t pin, + void *bsp_specific +); + +/** + * @brief Assigns a BSP specific function to the given pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] function BSP defined GPIO function. + * @param[in] pin_data Pointer to a BSP defined structure with BSP-specific + * data. + * + * @retval RTEMS_SUCCESSFUL Function was assigned successfully. + * @retval RTEMS_UNSATISFIED Could not assign the function to the pin. + */ +extern rtems_status_code rtems_gpio_bsp_select_specific_io( + uint32_t bank, + uint32_t pin, + uint32_t function, + void *pin_data +); + +/** + * @brief Configures a single GPIO pin pull resistor. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] mode The pull resistor mode. + * + * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured. + * @retval RTEMS_UNSATISFIED Could not set the pull mode. + */ +extern rtems_status_code rtems_gpio_bsp_set_resistor_mode( + uint32_t bank, + uint32_t pin, + rtems_gpio_pull_mode mode +); + +/** + * @brief Reads and returns a vector/bank interrupt event line. + * The bitmask should indicate with a 1 if the corresponding pin + * as a pending interrupt, or 0 if otherwise. The function + * should clear the interrupt event line before returning. + * This must be implemented by each BSP. + * + * @param[in] vector GPIO vector/bank. + * + * @retval Bitmask (max 32-bit) representing a GPIO bank, where a bit set + * indicates an active interrupt on that pin. + */ +extern uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector); + +/** + * @brief Calculates a vector number for a given GPIO bank. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * + * @retval The corresponding rtems_vector_number. + */ +extern rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank); + +/** + * @brief Enables interrupts to be generated on a given GPIO pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] interrupt Type of interrupt to enable for the pin. + * + * @retval RTEMS_SUCCESSFUL Interrupt successfully enabled for this pin. + * @retval RTEMS_UNSATISFIED Could not enable the interrupt on the pin. + */ +extern rtems_status_code rtems_gpio_bsp_enable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +); + +/** + * @brief Stops interrupts from being generated on a given GPIO pin. + * This must be implemented by each BSP. + * + * @param[in] bank GPIO bank number. + * @param[in] pin GPIO pin number within the given bank. + * @param[in] active_interrupt Interrupt type currently active on this pin. + * + * @retval RTEMS_SUCCESSFUL Interrupt successfully disabled for this pin. + * @retval RTEMS_UNSATISFIED Could not disable interrupts on this pin. + */ +extern rtems_status_code rtems_gpio_bsp_disable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_GPIO_H */ diff --git a/bsps/include/bsp/irq-generic.h b/bsps/include/bsp/irq-generic.h new file mode 100644 index 0000000000..187aea84d1 --- /dev/null +++ b/bsps/include/bsp/irq-generic.h @@ -0,0 +1,304 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief Generic BSP interrupt support API. + */ + +/* + * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette. + * + * Copyright (c) 2008, 2017 embedded brains GmbH. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * Copyright (c) 2016 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_IRQ_GENERIC_H +#define LIBBSP_SHARED_IRQ_GENERIC_H + +#include <stdbool.h> + +#include <rtems/irq-extension.h> +#include <rtems/score/assert.h> + +#ifdef RTEMS_SMP + #include <rtems/score/atomic.h> +#endif + +#include <bsp/irq.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !defined(BSP_INTERRUPT_VECTOR_MIN) || !defined(BSP_INTERRUPT_VECTOR_MAX) || (BSP_INTERRUPT_VECTOR_MAX + 1) < BSP_INTERRUPT_VECTOR_MIN + #error "invalid BSP_INTERRUPT_VECTOR_MIN or BSP_INTERRUPT_VECTOR_MAX" +#endif + +#if defined(BSP_INTERRUPT_USE_INDEX_TABLE) && !defined(BSP_INTERRUPT_HANDLER_TABLE_SIZE) + #error "if you define BSP_INTERRUPT_USE_INDEX_TABLE, you have to define BSP_INTERRUPT_HANDLER_TABLE_SIZE etc. as well" +#endif + +#if defined(BSP_INTERRUPT_NO_HEAP_USAGE) && !defined(BSP_INTERRUPT_USE_INDEX_TABLE) + #error "if you define BSP_INTERRUPT_NO_HEAP_USAGE, you have to define BSP_INTERRUPT_USE_INDEX_TABLE etc. as well" +#endif + +#define BSP_INTERRUPT_VECTOR_NUMBER \ + (BSP_INTERRUPT_VECTOR_MAX - BSP_INTERRUPT_VECTOR_MIN + 1) + +#ifndef BSP_INTERRUPT_HANDLER_TABLE_SIZE + #define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER +#endif + +/* Internal macros for SMP support, do not use externally */ +#ifdef RTEMS_SMP + #define bsp_interrupt_disable(level) do { (void) level; } while (0) + #define bsp_interrupt_enable(level) do { } while (0) + #define bsp_interrupt_fence(order) _Atomic_Fence(order) +#else + #define bsp_interrupt_disable(level) rtems_interrupt_disable(level) + #define bsp_interrupt_enable(level) rtems_interrupt_enable(level) + #define bsp_interrupt_fence(order) do { } while (0) +#endif + +#define bsp_interrupt_assert(e) _Assert(e) + +struct bsp_interrupt_handler_entry { + rtems_interrupt_handler handler; + void *arg; + const char *info; + struct bsp_interrupt_handler_entry *next; +}; + +typedef struct bsp_interrupt_handler_entry bsp_interrupt_handler_entry; + +extern bsp_interrupt_handler_entry bsp_interrupt_handler_table []; + +#ifdef BSP_INTERRUPT_USE_INDEX_TABLE + #if BSP_INTERRUPT_HANDLER_TABLE_SIZE < 0x100 + typedef uint8_t bsp_interrupt_handler_index_type; + #elif BSP_INTERRUPT_HANDLER_TABLE_SIZE < 0x10000 + typedef uint16_t bsp_interrupt_handler_index_type; + #else + typedef uint32_t bsp_interrupt_handler_index_type; + #endif + extern bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table []; +#endif + +static inline rtems_vector_number bsp_interrupt_handler_index( + rtems_vector_number vector +) +{ + #ifdef BSP_INTERRUPT_USE_INDEX_TABLE + return bsp_interrupt_handler_index_table [vector - BSP_INTERRUPT_VECTOR_MIN]; + #else + return vector - BSP_INTERRUPT_VECTOR_MIN; + #endif +} + +/** + * @defgroup bsp_interrupt BSP Interrupt Support + * + * @ingroup bsp_shared + * + * @brief Generic BSP Interrupt Support + * + * The BSP interrupt support manages a sequence of interrupt vector numbers + * ranging from @ref BSP_INTERRUPT_VECTOR_MIN to @ref BSP_INTERRUPT_VECTOR_MAX + * including the end points. It provides methods to + * @ref bsp_interrupt_handler_install() "install", + * @ref bsp_interrupt_handler_remove() "remove" and + * @ref bsp_interrupt_handler_dispatch() "dispatch" interrupt handlers for each + * vector number. It implements parts of the RTEMS interrupt manager. + * + * The entry points to a list of interrupt handlers are stored in a table + * (= handler table). + * + * You have to configure the BSP interrupt support in the <bsp/irq.h> file + * for each BSP. For a minimum configuration you have to provide + * @ref BSP_INTERRUPT_VECTOR_MIN and @ref BSP_INTERRUPT_VECTOR_MAX. + * + * For boards with small memory requirements you can define + * @ref BSP_INTERRUPT_USE_INDEX_TABLE. With an enabled index table the handler + * table will be accessed via a small index table. You can define the size of + * the handler table with @ref BSP_INTERRUPT_HANDLER_TABLE_SIZE. + * + * Normally new list entries are allocated from the heap. You may define + * @ref BSP_INTERRUPT_NO_HEAP_USAGE, if you do not want to use the heap. For + * this option you have to define @ref BSP_INTERRUPT_USE_INDEX_TABLE as well. + * + * You have to provide some special routines in your BSP (follow the links for + * the details): + * - bsp_interrupt_facility_initialize() + * - bsp_interrupt_vector_enable() + * - bsp_interrupt_vector_disable() + * - bsp_interrupt_handler_default() + * + * The following now deprecated functions are provided for backward + * compatibility: + * - BSP_get_current_rtems_irq_handler() + * - BSP_install_rtems_irq_handler() + * - BSP_install_rtems_shared_irq_handler() + * - BSP_remove_rtems_irq_handler() + * - BSP_rtems_irq_mngt_set() + * - BSP_rtems_irq_mngt_get() + * + * @{ + */ + +#ifdef BSP_INTERRUPT_CUSTOM_VALID_VECTOR + bool bsp_interrupt_is_valid_vector(rtems_vector_number vector); +#else + /** + * @brief Returns true if the interrupt vector with number @a vector is + * valid. + */ + static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector) + { + return (rtems_vector_number) BSP_INTERRUPT_VECTOR_MIN <= vector + && vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX; + } +#endif + +/** + * @brief Default interrupt handler. + * + * This routine will be called from bsp_interrupt_handler_dispatch() with the + * current vector number @a vector when the handler list for this vector is + * empty or the vector number is out of range. + * + * @note This function must cope with arbitrary vector numbers @a vector. + */ +void bsp_interrupt_handler_default(rtems_vector_number vector); + +/** + * @brief Initialize BSP interrupt support. + * + * You must call this function before you can install, remove and dispatch + * interrupt handlers. There is no protection against concurrent + * initialization. This function must be called at most once. The BSP + * specific bsp_interrupt_facility_initialize() function will be called after + * all internals are initialized. If the BSP specific initialization fails, + * then this is a fatal error. The fatal error source is + * RTEMS_FATAL_SOURCE_BSP and the fatal error code is + * BSP_FATAL_INTERRUPT_INITIALIZATION. + */ +void bsp_interrupt_initialize(void); + +/** + * @brief BSP specific initialization. + * + * This routine will be called form bsp_interrupt_initialize() and shall do the + * following: + * - Initialize the facilities that call bsp_interrupt_handler_dispatch(). For + * example on PowerPC the external exception handler. + * - Initialize the interrupt controller. You shall set the interrupt + * controller in a state such that interrupts are disabled for all vectors. + * The vectors will be enabled with your bsp_interrupt_vector_enable() function + * and disabled via your bsp_interrupt_vector_disable() function. These + * functions have to work afterwards. + * + * @return On success RTEMS_SUCCESSFUL shall be returned. + */ +rtems_status_code bsp_interrupt_facility_initialize(void); + +/** + * @brief Enables the interrupt vector with number @a vector. + * + * This function shall enable the vector at the corresponding facility (in most + * cases the interrupt controller). It will be called then the first handler + * is installed for the vector in bsp_interrupt_handler_install() for example. + * + * @note The implementation should use + * bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)) to valdiate the + * vector number. + * + * @note You must not install or remove an interrupt handler in this function. + * This may result in a deadlock. + */ +void bsp_interrupt_vector_enable(rtems_vector_number vector); + +/** + * @brief Disables the interrupt vector with number @a vector. + * + * This function shall disable the vector at the corresponding facility (in + * most cases the interrupt controller). It will be called then the last + * handler is removed for the vector in bsp_interrupt_handler_remove() for + * example. + * + * @note The implementation should use + * bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)) to valdiate the + * vector number. + * + * @note You must not install or remove an interrupt handler in this function. + * This may result in a deadlock. + */ +void bsp_interrupt_vector_disable(rtems_vector_number vector); + +/** + * @brief Sequencially calls all interrupt handlers for the vector number @a + * vector. + * + * If the vector number is out of range or the handler list is empty + * bsp_interrupt_handler_default() will be called with argument @a vector. + * + * You can call this function within every context which can be disabled via + * rtems_interrupt_disable(). + */ +static inline void bsp_interrupt_handler_dispatch(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + const bsp_interrupt_handler_entry *e = + &bsp_interrupt_handler_table [bsp_interrupt_handler_index(vector)]; + + do { + rtems_interrupt_handler handler; + void *arg; + + arg = e->arg; + bsp_interrupt_fence(ATOMIC_ORDER_ACQUIRE); + handler = e->handler; + (*handler)(arg); + + e = e->next; + } while (e != NULL); + } else { + bsp_interrupt_handler_default(vector); + } +} + +/** + * @brief Is interrupt handler empty. + * + * This routine returns true if the handler is empty and has not been + * initialised else false is returned. The interrupt lock is not used + * so this call can be used from within interrupts. + * + * @return If empty true shall be returned else false is returned. + */ +bool bsp_interrupt_handler_is_empty(rtems_vector_number vector); + +/** @} */ + +/* For internal use only */ +void bsp_interrupt_lock(void); + +/* For internal use only */ +void bsp_interrupt_unlock(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_IRQ_GENERIC_H */ diff --git a/bsps/include/bsp/irq-info.h b/bsps/include/bsp/irq-info.h new file mode 100644 index 0000000000..ea6d629e76 --- /dev/null +++ b/bsps/include/bsp/irq-info.h @@ -0,0 +1,56 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief Generic BSP interrupt information API. + */ + +/* + * Copyright (c) 2008, 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_IRQ_INFO_H +#define LIBBSP_SHARED_IRQ_INFO_H + +#include <rtems/shell.h> +#include <rtems/print.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Prints interrupt information via the printk plugin @a print with the + * context @a context. + */ +void bsp_interrupt_report_with_plugin( + const rtems_printer *printer +); + +/** + * @brief Prints interrupt information via the default printk plugin. + */ +void bsp_interrupt_report(void); + +/** + * @brief Shell command entry for interrupt information. + */ +extern struct rtems_shell_cmd_tt bsp_interrupt_shell_command; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_IRQ_INFO_H */ diff --git a/bsps/include/bsp/mm.h b/bsps/include/bsp/mm.h new file mode 100644 index 0000000000..2152f686ba --- /dev/null +++ b/bsps/include/bsp/mm.h @@ -0,0 +1,41 @@ +/** + * @file + * + * @ingroup shared_mm + * + * @brief MM Support + */ + +/* + * Copyright (c) 2013 Hesham AL-Matary. + * Copyright (c) 2013 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef __LIBBSP_MM_H +#define __LIBBSP_MM_H + +#include <stdint.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup shared_mm MM Support + * + * @ingroup shared_include + * + * @brief MM Support Package + */ + +void bsp_memory_management_initialize(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bsps/include/bsp/stackalloc.h b/bsps/include/bsp/stackalloc.h new file mode 100644 index 0000000000..89414c8e6e --- /dev/null +++ b/bsps/include/bsp/stackalloc.h @@ -0,0 +1,94 @@ +/** + * @file + * + * @ingroup bsp_stack + * + * @brief Task stack initialization, allocation and free functions. + */ + +/* + * Copyright (c) 2009-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_STACK_ALLOC_H +#define LIBBSP_SHARED_STACK_ALLOC_H + +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup bsp_stack Task Stack Allocator + * + * @ingroup bsp_shared + * + * @brief Task stack initialization, allocation and free functions. + * + * Initialize the task stack allocator with bsp_stack_initialize(). To enable + * the task stack allocator use the following in the system configuration: + * + * @code + * #include <bsp/stackalloc.h> + * + * #define CONFIGURE_INIT + * + * #include <confdefs.h> + * @endcode + * + * @{ + */ + +/** + * @brief Task stack allocator initialization for + * @ref CONFIGURE_TASK_STACK_ALLOCATOR_INIT. + */ +void bsp_stack_allocate_init(size_t stack_space_size); + +/** + * @brief Task stack allocator for @ref CONFIGURE_TASK_STACK_ALLOCATOR. + * + * In case the designated task stack space from bsp_stack_initialize() is + * completely in use the work space will be used to allocate the stack. + */ +void *bsp_stack_allocate(size_t size); + +/** + * @brief Task stack free function for @ref CONFIGURE_TASK_STACK_DEALLOCATOR. + */ +void bsp_stack_free(void *stack); + +/** + * @brief Task stack allocator initialization configuration option. + */ +#define CONFIGURE_TASK_STACK_ALLOCATOR_INIT bsp_stack_allocate_init + +/** + * @brief Task stack allocator configuration option. + */ +#define CONFIGURE_TASK_STACK_ALLOCATOR bsp_stack_allocate + +/** + * @brief Task stack deallocator configuration option. + */ +#define CONFIGURE_TASK_STACK_DEALLOCATOR bsp_stack_free + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_STACK_ALLOC_H */ diff --git a/bsps/include/bsp/u-boot.h b/bsps/include/bsp/u-boot.h new file mode 100644 index 0000000000..866cd9bbb0 --- /dev/null +++ b/bsps/include/bsp/u-boot.h @@ -0,0 +1,66 @@ +/** + * @file + * + * @ingroup shared_uboot + * + * @brief U_BOOT Support + */ + +/* + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_U_BOOT_H +#define LIBBSP_SHARED_U_BOOT_H + +#include <bsp/u-boot-config.h> + +#include <sys/types.h> +#include <stdint.h> + +#ifdef U_BOOT_64_BIT_PHYS_SIZE + typedef uint64_t phys_size_t; +#else + typedef unsigned long phys_size_t; +#endif + +#ifdef U_BOOT_GENERIC_BOARD_INFO + #include <bsp/u-boot-generic-board-info.h> +#else + #include <bsp/u-boot-board-info.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern bd_t bsp_uboot_board_info; + +/** + * @defgroup shared_uboot U_BOOT Support + * + * @ingroup shared_include + * + * @brief U_BOOT Support Package + */ + +void bsp_uboot_copy_board_info(const bd_t *src); + +/* FIXME: Do not use this function */ +void dumpUBootBDInfo(bd_t *u); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_SHARED_U_BOOT_H */ diff --git a/bsps/include/bsp/uart-output-char.h b/bsps/include/bsp/uart-output-char.h new file mode 100644 index 0000000000..a6648d1ad4 --- /dev/null +++ b/bsps/include/bsp/uart-output-char.h @@ -0,0 +1,60 @@ +/** + * @file + * + * @ingroup bsp_kit + * + * @brief Output character definitions for standard UARTs. + */ + +/* + * Copyright (c) 2010 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_SHARED_UART_OUTPUT_CHAR_H +#define LIBBSP_SHARED_UART_OUTPUT_CHAR_H + +#include <stdint.h> + +#include <bsp.h> + +#define CONSOLE_RBR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x00)) +#define CONSOLE_THR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x00)) +#define CONSOLE_DLL (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x00)) +#define CONSOLE_DLM (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x04)) +#define CONSOLE_IER (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x04)) +#define CONSOLE_IIR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x08)) +#define CONSOLE_FCR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x08)) +#define CONSOLE_LCR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x0C)) +#define CONSOLE_MCR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x10)) +#define CONSOLE_LSR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x14)) +#define CONSOLE_SCR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x1C)) +#define CONSOLE_ACR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x20)) +#define CONSOLE_ICR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x24)) +#define CONSOLE_FDR (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x28)) +#define CONSOLE_TER (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x30)) + +#define CONSOLE_LSR_RDR 0x1 +#define CONSOLE_LSR_THRE 0x20 +#define CONSOLE_LSR_TEMT 0x40 + +#define BSP_CONSOLE_UART_INIT(dll) \ + do { \ + CONSOLE_LCR = 0x00; \ + CONSOLE_IER = 0x00; \ + CONSOLE_LCR = 0x80; \ + CONSOLE_DLL = (dll & 0xFF); \ + CONSOLE_DLM = (dll >> 8); \ + CONSOLE_LCR = 0x03; \ + CONSOLE_FCR = 0x07; \ + } while (0) + +#endif /* LIBBSP_SHARED_UART_OUTPUT_CHAR_H */ diff --git a/bsps/include/bsp/utility.h b/bsps/include/bsp/utility.h new file mode 100644 index 0000000000..fee28f445a --- /dev/null +++ b/bsps/include/bsp/utility.h @@ -0,0 +1,156 @@ +/** + * @file + * + * @ingroup bsp_kit + * + * @brief Utility macros. + */ + +/* + * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBCPU_SHARED_UTILITY_H +#define LIBCPU_SHARED_UTILITY_H + +#include <stdint.h> + +#define BSP_BIT8(bit) \ + ((uint8_t) (((unsigned int) 1) << (bit))) + +#define BSP_MSK8(first_bit, last_bit) \ + ((uint8_t) ((BSP_BIT8((last_bit) - (first_bit) + 1) - 1) << (first_bit))) + +#define BSP_FLD8(val, first_bit, last_bit) \ + ((uint8_t) \ + ((((unsigned int) (val)) << (first_bit)) & BSP_MSK8(first_bit, last_bit))) + +#define BSP_FLD8GET(reg, first_bit, last_bit) \ + ((uint8_t) (((reg) & BSP_MSK8(first_bit, last_bit)) >> (first_bit))) + +#define BSP_FLD8SET(reg, val, first_bit, last_bit) \ + ((uint8_t) (((reg) & ~BSP_MSK8(first_bit, last_bit)) \ + | BSP_FLD8(val, first_bit, last_bit))) + +#define BSP_BIT16(bit) \ + ((uint16_t) (((unsigned int) 1) << (bit))) + +#define BSP_MSK16(first_bit, last_bit) \ + ((uint16_t) ((BSP_BIT16((last_bit) - (first_bit) + 1) - 1) << (first_bit))) + +#define BSP_FLD16(val, first_bit, last_bit) \ + ((uint16_t) \ + ((((unsigned int) (val)) << (first_bit)) & BSP_MSK16(first_bit, last_bit))) + +#define BSP_FLD16GET(reg, first_bit, last_bit) \ + ((uint16_t) (((reg) & BSP_MSK16(first_bit, last_bit)) >> (first_bit))) + +#define BSP_FLD16SET(reg, val, first_bit, last_bit) \ + ((uint16_t) (((reg) & ~BSP_MSK16(first_bit, last_bit)) \ + | BSP_FLD16(val, first_bit, last_bit))) + +#define BSP_BIT32(bit) \ + ((uint32_t) (((uint32_t) 1) << (bit))) + +#define BSP_MSK32(first_bit, last_bit) \ + ((uint32_t) ((BSP_BIT32((last_bit) - (first_bit) + 1) - 1) << (first_bit))) + +#define BSP_FLD32(val, first_bit, last_bit) \ + ((uint32_t) \ + ((((uint32_t) (val)) << (first_bit)) & BSP_MSK32(first_bit, last_bit))) + +#define BSP_FLD32GET(reg, first_bit, last_bit) \ + ((uint32_t) (((reg) & BSP_MSK32(first_bit, last_bit)) >> (first_bit))) + +#define BSP_FLD32SET(reg, val, first_bit, last_bit) \ + ((uint32_t) (((reg) & ~BSP_MSK32(first_bit, last_bit)) \ + | BSP_FLD32(val, first_bit, last_bit))) + +#define BSP_BIT64(bit) \ + ((uint64_t) (((uint64_t) 1) << (bit))) + +#define BSP_MSK64(first_bit, last_bit) \ + ((uint64_t) ((BSP_BIT64((last_bit) - (first_bit) + 1) - 1) << (first_bit))) + +#define BSP_FLD64(val, first_bit, last_bit) \ + ((uint64_t) \ + ((((uint64_t) (val)) << (first_bit)) & BSP_MSK64(first_bit, last_bit))) + +#define BSP_FLD64GET(reg, first_bit, last_bit) \ + ((uint64_t) (((reg) & BSP_MSK64(first_bit, last_bit)) >> (first_bit))) + +#define BSP_FLD64SET(reg, val, first_bit, last_bit) \ + ((uint64_t) (((reg) & ~BSP_MSK64(first_bit, last_bit)) \ + | BSP_FLD64(val, first_bit, last_bit))) + +#define BSP_BBIT8(bit) \ + BSP_BIT8(7 - (bit)) + +#define BSP_BMSK8(first_bit, last_bit) \ + BSP_MSK8(7 - (last_bit), 7 - (first_bit)) + +#define BSP_BFLD8(val, first_bit, last_bit) \ + BSP_FLD8(val, 7 - (last_bit), 7 - (first_bit)) + +#define BSP_BFLD8GET(reg, first_bit, last_bit) \ + BSP_FLD8GET(reg, 7 - (last_bit), 7 - (first_bit)) + +#define BSP_BFLD8SET(reg, val, first_bit, last_bit) \ + BSP_FLD8SET(reg, val, 7 - (last_bit), 7 - (first_bit)) + +#define BSP_BBIT16(bit) \ + BSP_BIT16(15 - (bit)) + +#define BSP_BMSK16(first_bit, last_bit) \ + BSP_MSK16(15 - (last_bit), 15 - (first_bit)) + +#define BSP_BFLD16(val, first_bit, last_bit) \ + BSP_FLD16(val, 15 - (last_bit), 15 - (first_bit)) + +#define BSP_BFLD16GET(reg, first_bit, last_bit) \ + BSP_FLD16GET(reg, 15 - (last_bit), 15 - (first_bit)) + +#define BSP_BFLD16SET(reg, val, first_bit, last_bit) \ + BSP_FLD16SET(reg, val, 15 - (last_bit), 15 - (first_bit)) + +#define BSP_BBIT32(bit) \ + BSP_BIT32(31 - (bit)) + +#define BSP_BMSK32(first_bit, last_bit) \ + BSP_MSK32(31 - (last_bit), 31 - (first_bit)) + +#define BSP_BFLD32(val, first_bit, last_bit) \ + BSP_FLD32(val, 31 - (last_bit), 31 - (first_bit)) + +#define BSP_BFLD32GET(reg, first_bit, last_bit) \ + BSP_FLD32GET(reg, 31 - (last_bit), 31 - (first_bit)) + +#define BSP_BFLD32SET(reg, val, first_bit, last_bit) \ + BSP_FLD32SET(reg, val, 31 - (last_bit), 31 - (first_bit)) + +#define BSP_BBIT64(bit) \ + BSP_BIT64(63 - (bit)) + +#define BSP_BMSK64(first_bit, last_bit) \ + BSP_MSK64(63 - (last_bit), 63 - (first_bit)) + +#define BSP_BFLD64(val, first_bit, last_bit) \ + BSP_FLD64(val, 63 - (last_bit), 63 - (first_bit)) + +#define BSP_BFLD64GET(reg, first_bit, last_bit) \ + BSP_FLD64GET(reg, 63 - (last_bit), 63 - (first_bit)) + +#define BSP_BFLD64SET(reg, val, first_bit, last_bit) \ + BSP_FLD64SET(reg, val, 63 - (last_bit), 63 - (first_bit)) + +#endif /* LIBCPU_SHARED_UTILITY_H */ diff --git a/bsps/include/bsp/vmeTsi148.h b/bsps/include/bsp/vmeTsi148.h new file mode 100644 index 0000000000..6183940a2d --- /dev/null +++ b/bsps/include/bsp/vmeTsi148.h @@ -0,0 +1,662 @@ +/** + * @file + * + * @ingroup shared_vmetsi148 + * + * @brief Driver for the Tundra Tsi148 pci-vme bridge + */ + +#ifndef VME_TSI148_DRIVER_H +#define VME_TSI148_DRIVER_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 <stdint.h> +#include <bsp/vme_am_defs.h> + + +/** + * @defgroup shared_vmetsi148 VMETSI148 Support + * + * @ingroup shared_vmeuniverse + * + * @brief VMETSI148 Support Package + */ + +/* NOTE: A64 currently not implemented */ + +/* These can be ored with the AM */ + +/* NOTE: unlike the universe, the tsi148 doesn't allow for disabling posted writes ! */ + +#define VME_MODE_PREFETCH_ENABLE VME_AM_IS_MEMORY +#define _LD_VME_MODE_PREFETCHSZ 24 +#define VME_MODE_PREFETCH_SIZE(x) (((x)&3)<<_LD_VME_MODE_PREFETCHSZ) + +/* These bits can be or'ed with the address-modifier when calling + * the 'XlateAddr' routine below to further qualify the + * search criteria. + */ +#define VME_MODE_MATCH_MASK (3<<30) +#define VME_MODE_EXACT_MATCH (2<<30) /* all bits must match */ +#define VME_MODE_AS_MATCH (1<<30) /* only A16/24/32 must match */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile uint32_t BERegister; /* emphasize contents are big endian */ + +/* + * Scan the PCI busses for the Nth (N=='instance') Tsi148 VME bridge. + * + * RETURNS: + * contents of the IRQ_LINE PCI config register on Success, + * the base address of the Tsi148 register block is stored in + * *pbase. + * -1 on error (no Tsi found, error accessing PCI config space). + * + * SIDE_EFFECTS: PCI busmaster and response to memory addresses is enabled. + */ +int +vmeTsi148FindPciBase(int instance, BERegister **pbase); + +/* Initialize driver for Nth Tsi148 device found. + * This routine does not change any registers but + * just scans the PCI bus for Tsi bridges and initializes + * a driver slot. + * + * RETURNS: 0 on success, nonzero on error (or if no Tsi148 + * device is found). + */ +int +vmeTsi148InitInstance(unsigned instance); + +/* Initialize driver with 1st Tsi148 bridge found + * RETURNS: (see vmeTsi148InitInstance()). + */ +int +vmeTsi148Init(void); + +/* Setup the tsi148 chip, i.e. disable most of its + * mappings, reset interrupts etc. + */ +void +vmeTsi148ResetXX(BERegister *base); + +/* Setup the tsi148 connected to the first driver slot */ +void +vmeTsi148Reset(void); + +/* Pull VME SYSRESET line */ +void +vmeTsi148ResetBusXX(BERegister *base); + +/* Pull VME SYSRESET line of the 1st controller */ +void +vmeTsi148ResetBus(void); + +/* NOTE: all non-'XX' versions of driver entry points which + * have an associated 'XX' entry point operate on the + * device connected to the 1st driver slot. + */ + +/* configure a outbound port + * + * port: port number 0..7 + * + * address_space: vxWorks compliant addressing mode identifier + * (see vme.h). The most important are: + * 0x0d - A32, Sup, Data + * 0x3d - A24, Sup, Data + * 0x2d - A16, Sup, Data + * additionally, the value 0 is accepted; it will + * disable this port. + * vme_address: address on the vme_bus of this port. + * local_address: address on the pci_bus of this port. + * length: size of this port. + * + * NOTE: the addresses and length parameters must meet certain alignment + * requirements (see Tsi148 documentation). + * + * RETURNS: 0 on success, -1 on failure. Error messages printed to stderr. + */ + +int +vmeTsi148OutboundPortCfgXX( + BERegister *base, + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long length); + +int +vmeTsi148OutboundPortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long length); + + +/* configure a VME inbound (PCI master) port */ +int +vmeTsi148InboundPortCfgXX( + BERegister *base, + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long length); + +int +vmeTsi148InboundPortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long pci_address, + unsigned long length); + +/* Translate an address through the bridge + * + * vmeTsi248XlateAddr(0,0,as,addr,&result) + * yields a VME a address that reflects + * a local memory location as seen from the VME bus through the + * tsi148 VME inbound port. + * + * Likewise does vmeTsi148XlateAddr(1,0,as,addr,&result) + * translate a VME bus addr (backwards, through the VME outbound + * port) to the PCI side of the bridge. + * + * A valid address space modifier must be specified. + * If VME_MODE_EXACT_MATCH is set, all the mode bits must + * match the requested mode. If VME_MODE_EXACT_MATCH is not + * set in the mode word, only the basic mode (address-space, + * sup/usr and pgm/data) is compared. + * + * The 'reverse' parameter may be used to find a reverse + * mapping, i.e. the pci address in a outbound window can be + * found if the respective vme address is known etc. + * + * RETURNS: translated address in *pbusAdrs / *plocalAdrs + * + * 0: success + * -1: address/modifier not found in any bridge port + * -2: invalid modifier + */ + +int +vmeTsi148XlateAddrXX( + BERegister *base, /* TSI 148 base address */ + int outbound, /* look in the outbound windows */ + int reverse, /* reverse mapping; for outbound ports: map local to VME */ + unsigned long as, /* address space */ + unsigned long aIn, /* address to look up */ + unsigned long *paOut/* where to put result */ + ); + +int +vmeTsi148XlateAddr( + int outbound, /* look in the outbound windows */ + int reverse, /* reverse mapping; for outbound: map local to VME */ + unsigned long as, /* address space */ + unsigned long aIn, /* address to look up */ + unsigned long *paOut/* where to put result */ + ); + + +/* avoid pulling stdio.h into this header. + * Applications that want a declaration of the + * following routines should + * #include <stdio.h> + * #define _VME_TSI148_DECLARE_SHOW_ROUTINES + * #include <vmeTsi148.h> + */ +#ifdef _VME_TSI148_DECLARE_SHOW_ROUTINES + +/* Print the current configuration of all outbound ports to + * f (stdout if NULL) + */ + +void +vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f); + +void +vmeTsi148OutboundPortsShow(FILE *f); + +/* Print the current configuration of all inbound ports to + * f (stdout if NULL) + */ + +void +vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f); + +void +vmeTsi148InboundPortsShow(FILE *f); + +#endif + + +/* Disable all in- or out-bound ports, respectively */ +void +vmeTsi148DisableAllInboundPortsXX(BERegister *base); + +void +vmeTsi148DisableAllInboundPorts(void); + +void +vmeTsi148DisableAllOutboundPortsXX(BERegister *base); + +void +vmeTsi148DisableAllOutboundPorts(void); + +# define TSI_VEAT_VES (1<<31) +# define TSI_VEAT_VEOF (1<<30) +# define TSI_VEAT_VESCL (1<<29) +# define TSI_VEAT_2eOT (1<<21) +# define TSI_VEAT_2eST (1<<20) +# define TSI_VEAT_BERR (1<<19) +# define TSI_VEAT_LWORD (1<<18) +# define TSI_VEAT_WRITE (1<<17) +# define TSI_VEAT_IACK (1<<16) +# define TSI_VEAT_DS1 (1<<15) +# define TSI_VEAT_DS0 (1<<14) +# define TSI_VEAT_AM(v) (((v)>>8)&63) +# define TSI_VEAT_XAM(v) ((v)&255) + +/* Check and clear the error (AKA 'exception') register. + * Note that the Tsi148 does *not* propagate VME bus errors of any kind to + * the PCI status register and hence this routine (or registering an ISR + * to the TSI_VERR_INT_VEC) is the only means for detecting a bus error. + * + * RETURNS: + * 0 if no error has occurred since this routine was last called. + * Contents of the 'VEAT' register (bit definitions as above) + * otherwise. + * If a non-NULL 'paddr' argument is provided then the lower 32-bit + * of the error address is stored in *paddr (only if return value is + * non-zero). + * + * SIDE EFFECTS: this routine clears the error attribute register, allowing + * for future errors to be latched. + */ +unsigned long +vmeTsi148ClearVMEBusErrorsXX(BERegister *base, uint32_t *paddr); + +unsigned long +vmeTsi148ClearVMEBusErrors(uint32_t *paddr); + +/* Map internal register block to VME. + * + * This routine is intended for BSP implementors. The registers must be + * accessible from VME so that the interrupt handler can flush the + * bridge FIFO (see below). + * + * vme_base: VME address where the TSI registers (4k) can be mapped. + * This VME address must fall into a range covered by + * any pre-configured outbound window. + * address_space: The desired VME address space. + * (all of SUP/USR/PGM/DATA are always accepted). + * + * See NOTES [vmeTsi148InstallIrqMgrAlt()] below for further information. + * + * RETURNS: 0 on success, nonzero on error. It is not possible (and results + * in a non-zero return code) to change the CRG VME address after + * initializing the interrupt manager as it uses the CRG. + */ +int +vmeTsi148MapCRGXX(BERegister *base, uint32_t vme_base, uint32_t address_space); + +int +vmeTsi148MapCRG(uint32_t vme_base, uint32_t address_space); + + +/* VME Interrupt Handler functionality */ + +/* we dont use the current RTEMS/BSP interrupt API for the + * following reasons: + * + * - RTEMS/BSP API does not pass an argument to the ISR :-( :-( + * - no separate vector space for VME vectors. Some vectors would + * have to overlap with existing PCI/ISA vectors. + * - RTEMS/BSP API allocates a structure for every possible vector + * - the irq_on(), irq_off() functions add more bloat than helping. + * They are (currently) only used by the framework to disable + * interrupts at the device level before removing a handler + * and to enable interrupts after installing a handler. + * These operations may as well be done by the driver itself. + * + * Hence, we maintain our own (VME) handler table and hook our PCI + * handler into the standard RTEMS/BSP environment. Our handler then + * dispatches VME interrupts. + */ + +typedef void (*VmeTsi148ISR) (void *usrArg, unsigned long vector); + +/* install a handler for a VME vector + * RETURNS 0 on success, nonzero on failure. + */ +int +vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR handler, void *usrArg); + +/* remove a handler for a VME vector. The vector and usrArg parameters + * must match the respective parameters used when installing the handler. + * RETURNS 0 on success, nonzero on failure. + */ +int +vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR handler, void *usrArg); + +/* query for the currently installed ISR and usr parameter at a given vector + * RETURNS: ISR or 0 (vector too big or no ISR installed) + */ +VmeTsi148ISR +vmeTsi148ISRGet(unsigned long vector, void **parg); + +/* utility routines to enable/disable a VME IRQ level + * + * To enable/disable the internal interrupt sources (special vectors above) + * pass a vector argument > 255. + * + * RETURNS 0 on success, nonzero on failure + */ +int +vmeTsi148IntEnable(unsigned int level); + +int +vmeTsi148IntDisable(unsigned int level); + +/* Check if an interrupt level or internal source is enabled: + * + * 'level': VME level 1..7 or internal special vector > 255 + * + * RETURNS: value > 0 if interrupt is currently enabled, + * zero if interrupt is currently disabled, + * -1 on error (invalid argument). + */ + +int +vmeTsi148IntIsEnabled(unsigned int level); + +/* Set IACK width (1,2, or 4 bytes) for a given interrupt level. + * + * 'width' arg may be 0,1,2 or 4. If zero, the currently active + * value is returned but not modified. + * + * RETURNS: old width or -1 if invalid argument. + */ + +int +vmeTsi148SetIackWidth(int level, int width); + +/* Change the routing of IRQ 'level' to 'pin'. + * If the BSP connects more than one of the four + * physical interrupt lines from the tsi148 to + * the board's PIC then you may change the physical + * line a given 'level' is using. By default, + * all 7 VME levels use the first wire (pin==0) and + * all internal sources use the (optional) second + * wire (pin==1) [The driver doesn't support more than + * four wires]. + * This feature is useful if you want to make use of + * different hardware priorities of the PIC. Let's + * say you want to give IRQ level 7 the highest priority. + * You could then give 'pin 0' a higher priority (at the + * PIC) and 'pin 1' a lower priority and issue. + * + * for ( i=1; i<7; i++ ) vmeTsi148IntRoute(i, 1); + * + * PARAMETERS: + * 'level' : VME interrupt level '1..7' or one of + * the internal sources. Pass the internal + * source's vector number (>=256). + * 'pin' : a value of 0 routes the requested IRQ to + * the first line registered with the manager, + * a value of 1 routes it to the second wire + * etc. + * + * RETURNS: 0 on success, nonzero on error (invalid arguments) + * + * NOTES: - DONT change the tsi148 'map' registers + * directly. The driver caches routing internally. + * - support for the extra wires (beyond wire #0) is + * board dependent. If the board only provides + * a single physical wire from the tsi148 to + * the PIC then the feature might not be available. + */ +int +vmeTsi148IntRoute(unsigned int level, unsigned int pin); + +/* Raise a VME Interrupt at 'level' and respond with 'vector' to a + * handler on the VME bus. (The handler could be a different board + * or the tsi148 itself. + * + * Note that you could install a interrupt handler at TSI_VME_SW_IACK_INT_VEC + * to be notified of an IACK cycle having completed. + * + * This routine is mainly FOR TESTING. + * + * NOTES: + * - the VICR register is modified. + * - NO MUTUAL EXCLUSION PROTECTION (reads VICR, modifies then writes back). + * If several users need access to VICR it is their responsibility to serialize access. + * + * Arguments: + * 'level': interrupt level, 1..7 + * 'vector': vector number (0..255) that the tsi148 puts on the bus in response to + * an IACK cycle. + * + * RETURNS: + * 0: Success + * -1: Invalid argument (level not 1..7, vector >= 256) + * -2: Interrupt 'level' already asserted (maybe nobody handles it). + * You can manually clear it be setting the IRQC bit in + * VICR. Make sure really nobody responds to avoid spurious + * interrupts (consult tsi148 docs). + */ + +int +vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector); + +int +vmeTsi148IntRaise(int level, unsigned vector); + +/* Loopback test of the VME interrupt subsystem. + * - installs ISRs on 'vector' and on TSI_VME_SW_IACK_INT_VEC + * - asserts VME interrupt 'level' + * - waits for both interrupts: 'ordinary' VME interrupt of 'level' and + * IACK completion interrupt ('special' vector TSI_VME_SW_IACK_INT_VEC). + * + * NOTES: + * - make sure no other handler responds to 'level'. + * - make sure no ISR is installed on both vectors yet. + * - ISRs installed by this routine are removed after completion. + * - no concurrent access protection of all involved resources + * (levels, vectors and registers [see vmeTsi148IntRaise()]) + * is implemented. + * - this routine is intended for TESTING (when implementing new BSPs etc.). + * - one RTEMS message queue is temporarily used (created/deleted). + * + * RETURNS: + * 0: Success. + * -1: Invalid arguments. + * 1: Test failed (outstanding interrupts). + * rtems_status_code: Failed RTEMS directive. + */ + +int +vmeTsi148IntLoopbackTst(int level, unsigned vector); + +/* use these special vectors to connect a handler to the + * tsi148 specific interrupts (such as "DMA done", SW or + * error irqs etc.) + * NOTE: The wrapper clears all status LINT bits (except + * for regular VME irqs). Also note that it is the user's + * responsibility to enable the necessary interrupts in + * LINT_EN + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER + * DEPENDS ON IT + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * Deliberately, these vectors match the universe driver's + */ +/* 256 no VOWN interrupt */ +#define TSI_DMA_INT_VEC 257 +#define TSI_LERR_INT_VEC 258 +#define TSI_VERR_INT_VEC 259 +/* 260 is reserved */ +#define TSI_VME_SW_IACK_INT_VEC 261 +/* 262 no PCI SW IRQ */ +#define TSI_SYSFAIL_INT_VEC 263 +#define TSI_ACFAIL_INT_VEC 264 +#define TSI_MBOX0_INT_VEC 265 +#define TSI_MBOX1_INT_VEC 266 +#define TSI_MBOX2_INT_VEC 267 +#define TSI_MBOX3_INT_VEC 268 +#define TSI_LM0_INT_VEC 269 +#define TSI_LM1_INT_VEC 270 +#define TSI_LM2_INT_VEC 271 +#define TSI_LM3_INT_VEC 272 + +/* New vectors; only on TSI148 */ +#define TSI_VIES_INT_VEC 273 +#define TSI_DMA1_INT_VEC 274 + +#define TSI_NUM_INT_VECS 275 + +#ifdef __INSIDE_RTEMS_BSP__ + +#include <stdarg.h> + +/* the tsi148 interrupt handler is capable of routing all sorts of + * (VME) interrupts to 4 different lines (some of) which may be hooked up + * in a (board specific) way to a PIC. + * + * This driver initially supports at most two lines (i.e., if the user + * doesn't re-route anything). By default, it routes the + * 7 VME interrupts to the main line and optionally, it routes the 'special' + * interrupts generated by the tsi148 itself (DMA done, SW irq etc.) + * to a second line. If no second line is available, all IRQs are routed + * to the main line. + * + * The routing of interrupts to the two lines can be modified (using + * the vmeTsi148IntRoute() call - see above - i.e., to make use of + * different hardware priorities and/or more physically available lines. + * + * Because the driver has no way to figure out which lines are actually + * wired to the PIC, this information has to be provided when installing + * the manager. + * + * Hence the manager sets up routing VME interrupts to 1 or 2 tsi148 + * OUTPUTS. However, it must also be told to which PIC INPUTS they + * are wired. + * Optionally, the first PIC input line can be read from PCI config space + * but the second must be passed to this routine. Note that the info read + * from PCI config space is wrong for some boards! + * + * PARAMETERS: + * flags: VMETSI148_IRQ_MGR_FLAG_SHARED: + * use the BSP_install_rtems_shared_irq_handler() instead + * of BSP_install_rtems_irq_handler(). Use this if the PIC + * line is used by other devices, too. + * CAVEAT: shared interrupts need RTEMS workspace, i.e., the + * VME interrupt manager can only be installed + * *after workspace is initialized* if 'shared' is nonzero + * (i.e., *not* from bspstart()). + * + * tsi_pin_0: to which output pin (of the tsi148) should the 7 + * VME irq levels be routed. + * + * pic_pin_0: specifies to which PIC input the 'main' output is + * wired on your board. If passed a value < 0, the driver + * reads this information from PCI config space ("IRQ line"). + * ... : up to three additional tsi_pin/pic_pin pairs can be + * specified if your board provides more physical wires. + * In any case must the varargs list be terminated by '-1'. + * + * RETURNS: 0 on success, -1 on failure. + * + * NOTES: The Tsi148 always does 'posted' writes through a FIFO buffer. + * This effectively makes VME write operations asynchronous + * which can have undesired side-effects. + * In particular, consider the case of an ISR clearing the + * interrupt condition by writing to a CSR. The write operation + * doesn't really do anything but goes into the FIFO and + * the user ISR returns. At this point, the interrupt manager + * may find the IRQ still pending, trying another IACK + * cycle. Because it is probable that at this time the FIFO + * has been flushed and the CSR-write operation been effective, + * the IACK then times out. + * Note that this phenomenon becomes more obvious as CPUs + * become faster. + * + * To avoid this race condition and many VME drivers having + * to be re-written, a VME read (having the desired side-effect + * of flushing the write FIFO) must be issued between the + * user ISR returning and the interrupt manager checking for + * more pending interrupts. + * + * Therefore, the BSP needs to map the Tsi148 register + * block to VME so that a read over VME can be effectuated. + * (In addition to being mapped to VME, the mapped address + * range must be accessible through an outbound window.) + */ + +#define VMETSI148_IRQ_MGR_FLAG_SHARED 1 +int +vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...); + +int +vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/vmeTsi148DMA.h b/bsps/include/bsp/vmeTsi148DMA.h new file mode 100644 index 0000000000..da7c99302b --- /dev/null +++ b/bsps/include/bsp/vmeTsi148DMA.h @@ -0,0 +1,102 @@ +/** + * @file + * + * @ingroup shared_vmetsi148dma + * + * @brief vmeTsi148DMA Support + */ + +#ifndef VME_TSI148_DMA_H +#define VME_TSI148_DMA_H + +#include <bsp/vmeTsi148.h> + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2006, 2007 + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 + */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup shared_vmetsi148dma DMA List + * + * @ingroup shared_vmeuniverse + * + * @brief DMA List access functions for use by bspVmeDmaList + */ + +extern struct VMEDmaListClassRec_ vmeTsi148DmaListClass; + +typedef struct VmeTsi148DmaListDescriptorRec_ *VmeTsi148DmaListDescriptor; + +int +vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom); + +int +vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom); + +int +vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d); + +int +vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d); + +int +vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes); + +int +vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes); + +uint32_t +vmeTsi148DmaStatusXX(BERegister *base, int channel); + +uint32_t +vmeTsi148DmaStatus(int channel); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/vmeUniverse.h b/bsps/include/bsp/vmeUniverse.h new file mode 100644 index 0000000000..7cb9f8d2de --- /dev/null +++ b/bsps/include/bsp/vmeUniverse.h @@ -0,0 +1,1045 @@ +/** + * @file + * + * @ingroup shared_vmeuniverse + * + * @brief Driver for the Tundra Universe II pci-vme bridge + */ + +#ifndef VME_UNIVERSE_UTIL_H +#define VME_UNIVERSE_UTIL_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2000-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 + */ + +/** + * @defgroup shared_vmeuniverse Register definitions + * + * @ingroup bsp_shared + * + * @brief all registers contents in PCI space are LITTLE ENDIAN + */ + +#ifdef __vxworks +#include <vme.h> +#else + +#include <bsp/vme_am_defs.h> + +#endif + +/* These bits can be or'ed with the address-modifier when calling + * the 'XlateAddr' routine below to further qualify the + * search criteria. + */ +#define VME_MODE_MATCH_MASK (3<<30) +#define VME_MODE_EXACT_MATCH (2<<30) /* all bits must match */ +#define VME_MODE_AS_MATCH (1<<30) /* only A16/24/32 must match */ + + +typedef unsigned long LERegister; /* emphasize contents are little endian */ + +/****** NOTE: USE OF VmeUniverseDMAPacket IS DEPRECATED ********* + ****** USE API IN VMEDMA.h INSTEAD *********/ + +/* NOTE: DMA packet descriptors MUST be 32 byte aligned */ +typedef struct VmeUniverseDMAPacketRec_ { + LERegister dctl __attribute__((aligned(32))); + LERegister dtbc __attribute__((packed)); + LERegister dla __attribute__((packed)); + LERegister dummy1 __attribute__((packed)); + LERegister dva __attribute__((packed)); + LERegister dummy2 __attribute__((packed)); + LERegister dcpp __attribute__((packed)); + LERegister dummy3 __attribute__((packed)); +} VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket; /* DEPRECATED */ + +/* PCI CSR register */ +#define UNIV_REGOFF_PCI_CSR 0x4 +# define UNIV_PCI_CSR_D_PE (1<<31) /* detected parity error; write 1 to clear */ +# define UNIV_PCI_CSR_S_SERR (1<<30) /* SERR (signalled error) asserted; write 1 to clear */ +# define UNIV_PCI_CSR_R_MA (1<<29) /* received master abort; write 1 to clear */ +# define UNIV_PCI_CSR_R_TA (1<<28) /* received target abort; write 1 to clear */ +# define UNIV_PCI_CSR_S_TA (1<<27) /* signalled target abort; write 1 to clear */ +# define UNIV_PCI_CSR_DEVSEL_MASK (3<<25) /* device select timing (RO) */ +# define UNIV_PCI_CSR_DP_D (1<<24) /* data parity error detected; write 1 to clear */ +# define UNIV_PCI_CSR_TFBBC (1<<23) /* target fast back to back capable (RO) */ +# define UNIV_PCI_CSR_MFBBC (1<<9) /* master fast back to back capable (RO) */ +# define UNIV_PCI_CSR_SERR_EN (1<<8) /* enable SERR driver */ +# define UNIV_PCI_CSR_WAIT (1<<7) /* wait cycle control (RO) */ +# define UNIV_PCI_CSR_PERESP (1<<6) /* parity error response enable */ +# define UNIV_PCI_CSR_VGAPS (1<<5) /* VGA palette snoop (RO) */ +# define UNIV_PCI_CSR_MWI_EN (1<<4) /* Memory write and invalidate enable (RO) */ +# define UNIV_PCI_CSR_SC (1<<3) /* special cycles (RO) */ +# define UNIV_PCI_CSR_BM (1<<2) /* master enable (MUST SET TO ENABLE VME SLAVES) */ +# define UNIV_PCI_CSR_MS (1<<1) /* target memory enable */ +# define UNIV_PCI_CSR_IOS (1<<0) /* target IO enable */ + +/* Special cycle (ADOH, RMW) control register */ +#define UNIV_REGOFF_SCYC_CTL 0x170 /* write 0 to disable */ +# define UNIV_SCYC_CTL_LAS_IO (1<<2) /* PCI address space (1: IO, 0: mem) */ +# define UNIV_SCYC_CTL_SCYC_RMW (1<<0) /* do a RMW cycle when reading PCI address */ +# define UNIV_SCYC_CTL_SCYC_ADOH (2<<0) /* do a ADOH cycle when reading/writing PCI address */ + +/* Special cycle address register */ +#define UNIV_REGOFF_SCYC_ADDR 0x174 /* PCI address (must be long word aligned) */ + +/* Special cycle Swap/Compare/Enable */ +#define UNIV_REGOFF_SCYC_EN 0x178 /* mask determining the bits involved in the compare and swap operations for VME RMW cycles */ + +/* Special cycle compare data register */ +#define UNIV_REGOFF_SCYC_CMP 0x17c /* data to compare with word returned from VME RMW read */ + +/* Special cycle swap data register */ +#define UNIV_REGOFF_SCYC_SWP 0x180 /* If enabled bits of CMP match, corresponding SWP bits are written back to VME (under control of EN) */ + +/* PCI miscellaneous register */ +#define UNIV_REGOFF_LMISC 0x184 +# define UNIV_LMISC_CRT_MASK (7<<28) /* Univ. I only, not used on II */ +# define UNIV_LMISC_CRT_INF (0<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_128_US (1<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_256_US (2<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_512_US (3<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_1024_US (4<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_2048_US (5<<28) /* Coupled Request Timeout */ +# define UNIV_LMISC_CRT_4096_US (6<<28) /* Coupled Request Timeout */ + +# define UNIV_LMISC_CWT_MASK (7<<24) /* coupled window timer */ +# define UNIV_LMISC_CWT_DISABLE 0 /* disabled (release VME after 1 coupled xaction) */ +# define UNIV_LMISC_CWT_16 (1<<24) /* 16 PCI clock cycles */ +# define UNIV_LMISC_CWT_32 (2<<24) /* 32 PCI clock cycles */ +# define UNIV_LMISC_CWT_64 (3<<24) /* 64 PCI clock cycles */ +# define UNIV_LMISC_CWT_128 (4<<24) /* 128 PCI clock cycles */ +# define UNIV_LMISC_CWT_256 (5<<24) /* 256 PCI clock cycles */ +# define UNIV_LMISC_CWT_512 (6<<24) /* 512 PCI clock cycles */ + +/* PCI Command Error Log Register */ +#define UNIV_REGOFF_L_CMDERR 0x18c +# define UNIV_L_CMDERR_CMDERR(reg) (((reg)>>28)&0xf) /* extract PCI cmd error log */ +# define UNIV_L_CMDERR_M_ERR (1<<27) /* multiple errors have occurred */ +# define UNIV_L_CMDERR_L_STAT (1<<23) /* PCI error log status valid (write 1 to clear and enable logging) */ + +/* PCI Address Error Log */ +#define UNIV_REGOFF_LAERR 0x190 /* PCI fault address (if L_CMDERR_L_STAT valid) */ +/* DMA Xfer Control Register */ +#define UNIV_REGOFF_DCTL 0x200 +# define UNIV_DCTL_L2V (1<<31) /* PCI->VME if set */ +# define UNIV_DCTL_VDW_MSK (3<<22) /* VME max. width mask 0x00c00000 */ +# define UNIV_DCTL_VDW_8 (0<<22) /* VME max. width 8 */ +# define UNIV_DCTL_VDW_16 (1<<22) /* VME max. width 16 */ +# define UNIV_DCTL_VDW_32 (2<<22) /* VME max. width 32 */ +# define UNIV_DCTL_VDW_64 (3<<22) /* VME max. width 64 */ +# define UNIV_DCTL_VAS_MSK (7<<16) /* VME AS mask 0x00070000 */ +# define UNIV_DCTL_VAS_A16 (0<<16) /* VME A16 */ +# define UNIV_DCTL_VAS_A24 (1<<16) /* VME A24 */ +# define UNIV_DCTL_VAS_A32 (2<<16) /* VME A32 */ +# define UNIV_DCTL_PGM_MSK (3<<14) /* VME PGM/DATA mask 0x0000c000 */ +# define UNIV_DCTL_PGM (1<<14) /* VME PGM(1)/DATA(0) */ +# define UNIV_DCTL_SUPER_MSK (3<<12) /* VME SUPER/USR mask 0x00003000 */ +# define UNIV_DCTL_SUPER (1<<12) /* VME SUPER(1)/USR(0) */ +# define UNIV_DCTL_NO_VINC (1<<9) /* VME no VME address increment [Universe IIa/b ONLY */ +# define UNIV_DCTL_VCT (1<<8) /* VME enable BLT */ +# define UNIV_DCTL_LD64EN (1<<7) /* PCI 64 enable */ + +/* DMA Xfer byte count register (is updated by DMA) */ +#define UNIV_REGOFF_DTBC 0x204 +/* DMA Xfer local (PCI) address (direction is set in DCTL) */ +#define UNIV_REGOFF_DLA 0x208 +/* DMA Xfer VME address (direction is set in DCTL) + * NOTE: (*UNIV_DVA) & ~7 == (*UNIV_DLA) & ~7 MUST HOLD + */ +#define UNIV_REGOFF_DVA 0x210 + +/* DMA Xfer VME command packet pointer + * NOTE: The address stored here MUST be 32-byte aligned + */ +#define UNIV_REGOFF_DCPP 0x218 +/* these bits are only used in linked lists */ +# define UNIV_DCPP_IMG_NULL (1<<0) /* last packet in list */ +# define UNIV_DCPP_IMG_PROCESSED (1<<1) /* packet processed */ + +/* DMA Xfer General Control/Status register */ +#define UNIV_REGOFF_DGCS 0x220 +# define UNIV_DGCS_GO (1<<31) /* start xfer */ +# define UNIV_DGCS_STOP_REQ (1<<30) /* stop xfer (immediate abort) */ +# define UNIV_DGCS_HALT_REQ (1<<29) /* halt xfer (abort after current packet) */ +# define UNIV_DGCS_CHAIN (1<<27) /* enable linked list mode */ +# define UNIV_DGCS_VON_MSK (7<<20) /* VON mask */ +# define UNIV_DGCS_VON_DONE (0<<20) /* VON counter disabled (do until done) */ +# define UNIV_DGCS_VON_256 (1<<20) /* VON yield bus after 256 bytes */ +# define UNIV_DGCS_VON_512 (2<<20) /* VON yield bus after 512 bytes */ +# define UNIV_DGCS_VON_1024 (3<<20) /* VON yield bus after 1024 bytes */ +# define UNIV_DGCS_VON_2048 (4<<20) /* VON yield bus after 2048 bytes */ +# define UNIV_DGCS_VON_4096 (5<<20) /* VON yield bus after 4096 bytes */ +# define UNIV_DGCS_VON_8192 (6<<20) /* VON yield bus after 8192 bytes */ +# define UNIV_DGCS_VON_16384 (7<<20) /* VON yield bus after 16384 bytes */ +# define UNIV_DGCS_VOFF_MSK (15<<16) /* VOFF mask */ +# define UNIV_DGCS_VOFF_0_US (0<<16) /* re-request VME master after 0 us */ +# define UNIV_DGCS_VOFF_2_US (8<<16) /* re-request VME master after 2 us */ +# define UNIV_DGCS_VOFF_4_US (9<<16) /* re-request VME master after 4 us */ +# define UNIV_DGCS_VOFF_8_US (10<<16)/* re-request VME master after 8 us */ +# define UNIV_DGCS_VOFF_16_US (1<<16) /* re-request VME master after 16 us */ +# define UNIV_DGCS_VOFF_32_US (2<<16) /* re-request VME master after 32 us */ +# define UNIV_DGCS_VOFF_64_US (3<<16) /* re-request VME master after 64 us */ +# define UNIV_DGCS_VOFF_128_US (4<<16) /* re-request VME master after 128 us */ +# define UNIV_DGCS_VOFF_256_US (5<<16) /* re-request VME master after 256 us */ +# define UNIV_DGCS_VOFF_512_US (6<<16) /* re-request VME master after 512 us */ +# define UNIV_DGCS_VOFF_1024_US (7<<16) /* re-request VME master after 1024 us */ +/* Status Bits (write 1 to clear) */ +# define UNIV_DGCS_ACT (1<<15) /* DMA active */ +# define UNIV_DGCS_STOP (1<<14) /* DMA stopped */ +# define UNIV_DGCS_HALT (1<<13) /* DMA halted */ +# define UNIV_DGCS_DONE (1<<11) /* DMA done (OK) */ +# define UNIV_DGCS_LERR (1<<10) /* PCI bus error */ +# define UNIV_DGCS_VERR (1<<9) /* VME bus error */ +# define UNIV_DGCS_P_ERR (1<<8) /* programming protocol error (e.g. PCI master disabled) */ +# define UNIV_DGCS_STATUS_CLEAR\ + (UNIV_DGCS_ACT|UNIV_DGCS_STOP|UNIV_DGCS_HALT|\ + UNIV_DGCS_DONE|UNIV_DGCS_LERR|UNIV_DGCS_VERR|UNIV_DGCS_P_ERR) +# define UNIV_DGCS_P_ERR (1<<8) /* programming protocol error (e.g. PCI master disabled) */ +/* Interrupt Mask Bits */ +# define UNIV_DGCS_INT_STOP (1<<6) /* interrupt when stopped */ +# define UNIV_DGCS_INT_HALT (1<<5) /* interrupt when halted */ +# define UNIV_DGCS_INT_DONE (1<<3) /* interrupt when done */ +# define UNIV_DGCS_INT_LERR (1<<2) /* interrupt on LERR */ +# define UNIV_DGCS_INT_VERR (1<<1) /* interrupt on VERR */ +# define UNIV_DGCS_INT_P_ERR (1<<0) /* interrupt on P_ERR */ +# define UNIV_DGCS_INT_MSK (0x0000006f) /* interrupt mask */ + +/* DMA Linked List Update Enable Register */ +#define UNIV_REGOFF_D_LLUE 0x224 +# define UNIV_D_LLUE_UPDATE (1<<31) + + +/* PCI (local) interrupt enable register */ +#define UNIV_REGOFF_LINT_EN 0x300 +# define UNIV_LINT_EN_LM3 (1<<23) /* location monitor 3 mask */ +# define UNIV_LINT_EN_LM2 (1<<22) /* location monitor 2 mask */ +# define UNIV_LINT_EN_LM1 (1<<21) /* location monitor 1 mask */ +# define UNIV_LINT_EN_LM0 (1<<20) /* location monitor 0 mask */ +# define UNIV_LINT_EN_MBOX3 (1<<19) /* mailbox 3 mask */ +# define UNIV_LINT_EN_MBOX2 (1<<18) /* mailbox 2 mask */ +# define UNIV_LINT_EN_MBOX1 (1<<17) /* mailbox 1 mask */ +# define UNIV_LINT_EN_MBOX0 (1<<16) /* mailbox 0 mask */ +# define UNIV_LINT_EN_ACFAIL (1<<15) /* ACFAIL irq mask */ +# define UNIV_LINT_EN_SYSFAIL (1<<14) /* SYSFAIL irq mask */ +# define UNIV_LINT_EN_SW_INT (1<<13) /* PCI (local) software irq */ +# define UNIV_LINT_EN_SW_IACK (1<<12) /* VME software IACK mask */ +# define UNIV_LINT_EN_VERR (1<<10) /* PCI VERR irq mask */ +# define UNIV_LINT_EN_LERR (1<<9) /* PCI LERR irq mask */ +# define UNIV_LINT_EN_DMA (1<<8) /* PCI DMA irq mask */ +# define UNIV_LINT_EN_VIRQ7 (1<<7) /* VIRQ7 mask (universe does IACK automatically) */ +# define UNIV_LINT_EN_VIRQ6 (1<<6) /* VIRQ6 mask */ +# define UNIV_LINT_EN_VIRQ5 (1<<5) /* VIRQ5 mask */ +# define UNIV_LINT_EN_VIRQ4 (1<<4) /* VIRQ4 mask */ +# define UNIV_LINT_EN_VIRQ3 (1<<3) /* VIRQ3 mask */ +# define UNIV_LINT_EN_VIRQ2 (1<<2) /* VIRQ2 mask */ +# define UNIV_LINT_EN_VIRQ1 (1<<1) /* VIRQ1 mask */ +# define UNIV_LINT_EN_VOWN (1<<0) /* VOWN mask */ + +/* PCI (local) interrupt status register */ +#define UNIV_REGOFF_LINT_STAT 0x304 +# define UNIV_LINT_STAT_LM3 (1<<23) /* location monitor 3 status */ +# define UNIV_LINT_STAT_LM2 (1<<22) /* location monitor 2 status */ +# define UNIV_LINT_STAT_LM1 (1<<21) /* location monitor 1 status */ +# define UNIV_LINT_STAT_LM0 (1<<20) /* location monitor 0 status */ +# define UNIV_LINT_STAT_MBOX3 (1<<19) /* mailbox 3 status */ +# define UNIV_LINT_STAT_MBOX2 (1<<18) /* mailbox 2 status */ +# define UNIV_LINT_STAT_MBOX1 (1<<17) /* mailbox 1 status */ +# define UNIV_LINT_STAT_MBOX0 (1<<16) /* mailbox 0 status */ +# define UNIV_LINT_STAT_ACFAIL (1<<15) /* ACFAIL irq status */ +# define UNIV_LINT_STAT_SYSFAIL (1<<14) /* SYSFAIL irq status */ +# define UNIV_LINT_STAT_SW_INT (1<<13) /* PCI (local) software irq */ +# define UNIV_LINT_STAT_SW_IACK (1<<12) /* VME software IACK status */ +# define UNIV_LINT_STAT_VERR (1<<10) /* PCI VERR irq status */ +# define UNIV_LINT_STAT_LERR (1<<9) /* PCI LERR irq status */ +# define UNIV_LINT_STAT_DMA (1<<8) /* PCI DMA irq status */ +# define UNIV_LINT_STAT_VIRQ7 (1<<7) /* VIRQ7 status */ +# define UNIV_LINT_STAT_VIRQ6 (1<<6) /* VIRQ6 status */ +# define UNIV_LINT_STAT_VIRQ5 (1<<5) /* VIRQ5 status */ +# define UNIV_LINT_STAT_VIRQ4 (1<<4) /* VIRQ4 status */ +# define UNIV_LINT_STAT_VIRQ3 (1<<3) /* VIRQ3 status */ +# define UNIV_LINT_STAT_VIRQ2 (1<<2) /* VIRQ2 status */ +# define UNIV_LINT_STAT_VIRQ1 (1<<1) /* VIRQ1 status */ +# define UNIV_LINT_STAT_VOWN (1<<0) /* VOWN status */ +# define UNIV_LINT_STAT_CLR (0xfff7ff)/* Clear all status bits */ + +/* PCI (local) interrupt map 0 register */ +#define UNIV_REGOFF_LINT_MAP0 0x308 /* mapping of VME IRQ sources to PCI irqs */ +# define UNIV_LINT_MAP0_VIRQ7(lint) (((lint)&0x7)<<(7*4)) +# define UNIV_LINT_MAP0_VIRQ6(lint) (((lint)&0x7)<<(6*4)) +# define UNIV_LINT_MAP0_VIRQ5(lint) (((lint)&0x7)<<(5*4)) +# define UNIV_LINT_MAP0_VIRQ4(lint) (((lint)&0x7)<<(4*4)) +# define UNIV_LINT_MAP0_VIRQ3(lint) (((lint)&0x7)<<(3*4)) +# define UNIV_LINT_MAP0_VIRQ2(lint) (((lint)&0x7)<<(2*4)) +# define UNIV_LINT_MAP0_VIRQ1(lint) (((lint)&0x7)<<(1*4)) +# define UNIV_LINT_MAP0_VOWN(lint) (((lint)&0x7)<<(0*4)) + +#define UNIV_REGOFF_LINT_MAP1 0x30c /* mapping of internal / VME IRQ sources to PCI irqs */ +# define UNIV_LINT_MAP1_ACFAIL(lint) (((lint)&0x7)<<(7*4)) +# define UNIV_LINT_MAP1_SYSFAIL(lint) (((lint)&0x7)<<(6*4)) +# define UNIV_LINT_MAP1_SW_INT(lint) (((lint)&0x7)<<(5*4)) +# define UNIV_LINT_MAP1_SW_IACK(lint) (((lint)&0x7)<<(4*4)) +# define UNIV_LINT_MAP1_VERR(lint) (((lint)&0x7)<<(2*4)) +# define UNIV_LINT_MAP1_LERR(lint) (((lint)&0x7)<<(1*4)) +# define UNIV_LINT_MAP1_DMA(lint) (((lint)&0x7)<<(0*4)) + +/* enabling of generation of VME bus IRQs, TODO */ +#define UNIV_REGOFF_VINT_EN 0x310 +# define UNIV_VINT_EN_DISABLE_ALL 0 +# define UNIV_VINT_EN_SWINT (1<<12) +# define UNIV_VINT_EN_SWINT_LVL(l) (1<<(((l)&7)+24)) /* universe II only */ + + +/* status of generation of VME bus IRQs */ +#define UNIV_REGOFF_VINT_STAT 0x314 +# define UNIV_VINT_STAT_LINT(lint) (1<<((lint)&7)) +# define UNIV_VINT_STAT_LINT_MASK (0xff) +# define UNIV_VINT_STAT_CLR (0xfe0f17ff) +# define UNIV_VINT_STAT_SWINT(l) (1<<(((l)&7)+24)) + +#define UNIV_REGOFF_VINT_MAP0 0x318 /* VME destination of PCI IRQ source, TODO */ + +#define UNIV_REGOFF_VINT_MAP1 0x31c /* VME destination of PCI IRQ source, TODO */ +# define UNIV_VINT_MAP1_SWINT(level) (((level)&0x7)<<16) + +/* NOTE: The universe seems to always set LSB (which has a special purpose in + * the STATID register: enable raising a SW_INT on IACK) on the + * vector it puts out on the bus... + */ +#define UNIV_REGOFF_VINT_STATID 0x320 /* our status/id response to IACK, TODO */ +# define UNIV_VINT_STATID(id) ((id)<<24) + +#define UNIV_REGOFF_VIRQ1_STATID 0x324 /* status/id of VME IRQ level 1 */ +#define UNIV_REGOFF_VIRQ2_STATID 0x328 /* status/id of VME IRQ level 2 */ +#define UNIV_REGOFF_VIRQ3_STATID 0x32c /* status/id of VME IRQ level 3 */ +#define UNIV_REGOFF_VIRQ4_STATID 0x330 /* status/id of VME IRQ level 4 */ +#define UNIV_REGOFF_VIRQ5_STATID 0x334 /* status/id of VME IRQ level 5 */ +#define UNIV_REGOFF_VIRQ6_STATID 0x338 /* status/id of VME IRQ level 6 */ +#define UNIV_REGOFF_VIRQ7_STATID 0x33c /* status/id of VME IRQ level 7 */ +# define UNIV_VIRQ_ERR (1<<8) /* set if universe encountered a bus error when doing IACK */ +# define UNIV_VIRQ_STATID_MASK (0xff) + +#define UNIV_REGOFF_LINT_MAP2 0x340 /* mapping of internal sources to PCI irqs */ +# define UNIV_LINT_MAP2_LM3(lint) (((lint)&0x7)<<7*4) /* location monitor 3 */ +# define UNIV_LINT_MAP2_LM2(lint) (((lint)&0x7)<<6*4) /* location monitor 2 */ +# define UNIV_LINT_MAP2_LM1(lint) (((lint)&0x7)<<5*4) /* location monitor 1 */ +# define UNIV_LINT_MAP2_LM0(lint) (((lint)&0x7)<<4*4) /* location monitor 0 */ +# define UNIV_LINT_MAP2_MBOX3(lint) (((lint)&0x7)<<3*4) /* mailbox 3 */ +# define UNIV_LINT_MAP2_MBOX2(lint) (((lint)&0x7)<<2*4) /* mailbox 2 */ +# define UNIV_LINT_MAP2_MBOX1(lint) (((lint)&0x7)<<1*4) /* mailbox 1 */ +# define UNIV_LINT_MAP2_MBOX0(lint) (((lint)&0x7)<<0*4) /* mailbox 0 */ + +#define UNIV_REGOFF_VINT_MAP2 0x344 /* mapping of internal sources to VME irqs */ +# define UNIV_VINT_MAP2_MBOX3(vint) (((vint)&0x7)<<3*4) /* mailbox 3 */ +# define UNIV_VINT_MAP2_MBOX2(vint) (((vint)&0x7)<<2*4) /* mailbox 2 */ +# define UNIV_VINT_MAP2_MBOX1(vint) (((vint)&0x7)<<1*4) /* mailbox 1 */ +# define UNIV_VINT_MAP2_MBOX0(vint) (((vint)&0x7)<<0*4) /* mailbox 0 */ + +#define UNIV_REGOFF_MBOX0 0x348 /* mailbox 0 */ +#define UNIV_REGOFF_MBOX1 0x34c /* mailbox 1 */ +#define UNIV_REGOFF_MBOX2 0x350 /* mailbox 2 */ +#define UNIV_REGOFF_MBOX3 0x354 /* mailbox 3 */ + +#define UNIV_REGOFF_SEMA0 0x358 /* semaphore 0 */ +#define UNIV_REGOFF_SEMA1 0x35c /* semaphore 0 */ +/* TODO define semaphore register bits */ + +#define UNIV_REGOFF_MAST_CTL 0x400 /* master control register */ +# define UNIV_MAST_CTL_MAXRTRY(val) (((val)&0xf)<<7*4) /* max # of pci master retries */ +# define UNIV_MAST_CTL_PWON(val) (((val)&0xf)<<6*4) /* posted write xfer count */ +# define UNIV_MAST_CTL_VRL(val) (((val)&0x3)<<22) /* VME bus request level */ +# define UNIV_MAST_CTL_VRM (1<<21) /* bus request mode (demand = 0, fair = 1) */ +# define UNIV_MAST_CTL_VREL (1<<20) /* bus release mode (when done = 0, on request = 1) */ +# define UNIV_MAST_CTL_VOWN (1<<19) /* bus ownership (release = 0, acquire/hold = 1) */ +# define UNIV_MAST_CTL_VOWN_ACK (1<<18) /* bus ownership (not owned = 0, acquired/held = 1) */ +# define UNIV_MAST_CTL_PABS(val) (((val)&0x3)<<3*4) /* PCI aligned burst size (32,64,128 byte / 0x3 is reserved) */ +# define UNIV_MAST_CTL_BUS_NO(val) (((val)&0xff)<<0*4) /* PCI bus number */ + +#define UNIV_REGOFF_MISC_CTL 0x404 /* misc control register */ +# define UNIV_MISC_CTL_VBTO(val) (((val)&0x7)<<7*4) /* VME bus timeout (0=disable, 16*2^(val-1) us) */ +# define UNIV_MISC_CTL_VARB (1<<26) /* VME bus arbitration mode (0=round robin, 1= priority) */ +# define UNIV_MISC_CTL_VARBTO(val) (((val)&0x3)<<6*4) /* arbitration time out: disable, 16us, 256us, reserved */ +# define UNIV_MISC_CTL_SW_LRST (1<<23) /* software PCI reset */ +# define UNIV_MISC_CTL_SW_SYSRST (1<<22) /* software VME reset */ +# define UNIV_MISC_CTL_BI (1<<20) /* BI mode */ +# define UNIV_MISC_CTL_ENGBI (1<<19) /* enable global BI mode initiator */ +# define UNIV_MISC_CTL_SYSCON (1<<17) /* (R/W) 1:universe is system controller */ +# define UNIV_MISC_CTL_V64AUTO (1<<16) /* (R/W) 1:initiate VME64 auto id slave participation */ + +/* U2SPEC described in VGM manual */ +/* NOTE: the Joerger vtr10012_8 needs the timing to be tweaked!!!! READt27 must be _no_delay_ + */ +#define UNIV_REGOFF_U2SPEC 0x4fc +# define UNIV_U2SPEC_DTKFLTR (1<<12) /* DTAck filter: 0: slow, better filter; 1: fast, poorer filter */ +# define UNIV_U2SPEC_MASt11 (1<<10) /* Master parameter t11 (DS hi time during BLT and MBLTs) */ +# define UNIV_U2SPEC_READt27_DEFAULT (0<<8) /* VME master parameter t27: (latch data after DTAck + 25ns) */ +# define UNIV_U2SPEC_READt27_FAST (1<<8) /* VME master parameter t27: (latch data faster than 25ns) */ +# define UNIV_U2SPEC_READt27_NODELAY (2<<8) /* VME master parameter t27: (latch data without any delay) */ +# define UNIV_U2SPEC_POSt28_FAST (1<<2) /* VME slave parameter t28: (faster time of DS to DTAck for posted write) */ +# define UNIV_U2SPEC_PREt28_FAST (1<<0) /* VME slave parameter t28: (faster time of DS to DTAck for prefetch read) */ + +/* Location Monitor control register */ +#define UNIV_REGOFF_LM_CTL 0xf64 +# define UNIV_LM_CTL_EN (1<<31) /* image enable */ +# define UNIV_LM_CTL_PGM (1<<23) /* program AM */ +# define UNIV_LM_CTL_DATA (1<<22) /* data AM */ +# define UNIV_LM_CTL_SUPER (1<<21) /* supervisor AM */ +# define UNIV_LM_CTL_USER (1<<20) /* user AM */ +# define UNIV_LM_CTL_VAS_A16 (0<<16) /* A16 */ +# define UNIV_LM_CTL_VAS_A24 (1<<16) /* A16 */ +# define UNIV_LM_CTL_VAS_A32 (2<<16) /* A16 */ + +/* Location Monitor base address */ +#define UNIV_REGOFF_LM_BS 0xf68 + +/* VMEbus register access image control register */ +#define UNIV_REGOFF_VRAI_CTL 0xf70 +# define UNIV_VRAI_CTL_EN (1<<31) /* image enable */ +# define UNIV_VRAI_CTL_PGM (1<<23) /* program AM */ +# define UNIV_VRAI_CTL_DATA (1<<22) /* data AM */ +# define UNIV_VRAI_CTL_SUPER (1<<21) /* supervisor AM */ +# define UNIV_VRAI_CTL_USER (1<<20) /* user AM */ +# define UNIV_VRAI_CTL_VAS_A16 (0<<16) /* A16 */ +# define UNIV_VRAI_CTL_VAS_A24 (1<<16) /* A14 */ +# define UNIV_VRAI_CTL_VAS_A32 (2<<16) /* A32 */ +# define UNIV_VRAI_CTL_VAS_MSK (3<<16) + +/* VMEbus register acces image base address register */ +#define UNIV_REGOFF_VRAI_BS 0xf74 + +/* VMEbus CSR control register */ +#define UNIV_REGOFF_VCSR_CTL 0xf80 +# define UNIV_VCSR_CTL_EN (1<<31) /* image enable */ +# define UNIV_VCSR_CTL_LAS_PCI_MEM (0<<0) /* pci mem space */ +# define UNIV_VCSR_CTL_LAS_PCI_IO (1<<0) /* pci IO space */ +# define UNIV_VCSR_CTL_LAS_PCI_CFG (2<<0) /* pci config space */ + +/* VMEbus CSR translation offset */ +#define UNIV_REGOFF_VCSR_TO 0xf84 + +/* VMEbus AM code error log */ +#define UNIV_REGOFF_V_AMERR 0xf88 +# define UNIV_V_AMERR_AMERR(reg) (((reg)>>26)&0x3f) /* extract error log code */ +# define UNIV_V_AMERR_IACK (1<<25) /* VMEbus IACK signal */ +# define UNIV_V_AMERR_M_ERR (1<<24) /* multiple errors occurred */ +# define UNIV_V_AMERR_V_STAT (1<<23) /* log status valid (write 1 to clear) */ + +/* VMEbus address error log */ +#define UNIV_REGOFF_VAERR 0xf8c /* address of fault address (if MERR_V_STAT valid) */ + +/* VMEbus CSR bit clear register */ +#define UNIV_REGOFF_VCSR_CLR 0xff4 +# define UNIV_VCSR_CLR_RESET (1<<31) /* read/negate LRST (can only be written from VME bus */ +# define UNIV_VCSR_CLR_SYSFAIL (1<<30) /* read/negate SYSFAIL */ +# define UNIV_VCSR_CLR_FAIL (1<<29) /* read: board has failed */ + +/* VMEbus CSR bit set register */ +#define UNIV_REGOFF_VCSR_SET (0xff8) +# define UNIV_VCSR_SET_RESET (1<<31) /* read/assert LRST (can only be written from VME bus */ +# define UNIV_VCSR_SET_SYSFAIL (1<<30) /* read/assert SYSFAIL */ +# define UNIV_VCSR_SET_FAIL (1<<29) /* read: board has failed */ + +/* VMEbus CSR base address register */ +#define UNIV_REGOFF_VCSR_BS 0xffc +#define UNIV_VCSR_BS_MASK (0xf8000000) + +/* offset of universe registers in VME-CSR slot */ +#define UNIV_CSR_OFFSET 0x7f000 + +#ifdef __cplusplus +extern "C" { +#endif + +/* base address and IRQ line of 1st universe bridge + * NOTE: vmeUniverseInit() must be called before + * these may be used. + */ +extern volatile LERegister *vmeUniverse0BaseAddr; +extern int vmeUniverse0PciIrqLine; + + +/* Initialize the driver */ +int +vmeUniverseInit(void); + +/* setup the universe chip, i.e. disable most of its + * mappings, reset interrupts etc. + */ +void +vmeUniverseReset(void); + +/* avoid pulling stdio.h into this header. + * Applications that want a declaration of the + * following routines should + * #include <stdio.h> + * #define _VME_UNIVERSE_DECLARE_SHOW_ROUTINES + * #include <vmeUniverse.h> + */ +/* print the current configuration of all master ports to + * f (stderr if NULL) + */ +void +vmeUniverseMasterPortsShow(FILE *f); + +/* print the current configuration of all slave ports to + * f (stderr if NULL) + */ +void +vmeUniverseSlavePortsShow(FILE *f); + +/* disable all master or slave ports, respectively */ +void +vmeUniverseDisableAllMasters(void); + +void +vmeUniverseDisableAllSlaves(void); + +/* configure a master port + * + * port: port number 0..3 (0..7 for a UniverseII) + * + * address_space: vxWorks compliant addressing mode identifier + * (see vme.h). The most important are: + * 0x0d - A32, Sup, Data + * 0x3d - A24, Sup, Data + * 0x2d - A16, Sup, Data + * additionally, the value 0 is accepted; it will + * disable this port. + * vme_address: address on the vme_bus of this port. + * local_address: address on the pci_bus of this port. + * length: size of this port. + * + * NOTE: the addresses and length parameters must be aligned on a + * 2^16 byte (0x10000) boundary, except for port 4 (only available + * on a UniverseII), where the alignment can be 4k (4096). + * + * RETURNS: 0 on success, -1 on failure. Error messages printed to stderr. + */ + +int +vmeUniverseMasterPortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long local_address, + unsigned long length); + +/* translate an address through the bridge + * + * vmeUniverseXlateAddr(0,0,as,addr,&result) + * yields a VME a address that reflects + * a local memory location as seen from the VME bus through the universe + * VME slave. + * + * likewise does vmeUniverseXlateAddr(1,0,as,addr,&result) + * translate a VME bus addr (through the VME master) to the + * PCI side of the bridge. + * + * a valid address space modifier must be specified. + * + * The 'reverse' parameter may be used to find a reverse + * mapping, i.e. the pci address in a master window can be + * found if the respective vme address is known etc. + * + * RETURNS: translated address in *pbusAdrs / *plocalAdrs + * + * 0: success + * -1: address/modifier not found in any bridge port + * -2: invalid modifier + */ +int +vmeUniverseXlateAddr( + int master, /* look in the master windows */ + int reverse, /* reverse mapping; for masters: map local to VME */ + unsigned long as, /* address space */ + unsigned long addr, /* address to look up */ + unsigned long *paOut/* where to put result */ + ); + +/* configure a VME slave (PCI master) port */ +int +vmeUniverseSlavePortCfg( + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long local_address, + unsigned long length); + +/****** NOTE: USE OF vmeUniverseStartDMA IS DEPRECATED ********* + ****** USE API IN VMEDMA.h/vmeUniverseDMA.h INSTEAD *********/ + +/* start a (direct, not linked) DMA transfer + * + * NOTE: DCTL and DGCS must be set up + * prior to calling this routine + */ +int +vmeUniverseStartDMA( + unsigned long local_addr, + unsigned long vme_addr, + unsigned long count); /* DEPRECATED */ + +int +vmeUniverseStartDMAXX( + volatile LERegister *ubase, + unsigned long local_addr, + unsigned long vme_addr, + unsigned long count); /* DEPRECATED */ + + +/* read a register in PCI memory space + * (offset being one of the declared constants) + */ +unsigned long +vmeUniverseReadReg(unsigned long offset); + +/* write a register in PCI memory space */ +void +vmeUniverseWriteReg(unsigned long value, unsigned long offset); + +/* convert an array of unsigned long values to LE (as needed + * when the universe reads e.g. DMA descriptors from PCI) + */ +void +vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num); + +/* reset the VME bus */ +void +vmeUniverseResetBus(void); + +/* The ...XX routines take the universe base address as an additional + * argument - this allows for programming secondary devices. + */ + +unsigned long +vmeUniverseReadRegXX(volatile LERegister *ubase, unsigned long offset); + +void +vmeUniverseWriteRegXX(volatile LERegister *ubase, unsigned long value, unsigned long offset); + +int +vmeUniverseXlateAddrXX( + volatile LERegister *ubase, + int master, + int reverse, + unsigned long as, + unsigned long addr, + unsigned long *paOut + ); + +int +vmeUniverseMasterPortCfgXX( + volatile LERegister *ubase, + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long local_address, + unsigned long length); + +int +vmeUniverseSlavePortCfgXX( + volatile LERegister *ubase, + unsigned long port, + unsigned long address_space, + unsigned long vme_address, + unsigned long local_address, + unsigned long length); + +void +vmeUniverseDisableAllMastersXX(volatile LERegister *ubase); + +void +vmeUniverseDisableAllSlavesXX(volatile LERegister *ubase); + +/* print the current configuration of all master ports to + * f (stderr if NULL) + */ +void +vmeUniverseMasterPortsShowXX( + volatile LERegister *ubase,FILE *f); + +/* print the current configuration of all slave ports to + * f (stderr if NULL) + */ +void +vmeUniverseSlavePortsShowXX( + volatile LERegister *ubase,FILE *f); + +/* Raise a VME Interrupt at 'level' and respond with 'vector' to a + * handler on the VME bus. (The handler could be a different board + * or the universe itself - [only works with universe II]). + * + * Note that you could install a interrupt handler at UNIV_VME_SW_IACK_INT_VEC + * to be notified of an IACK cycle having completed. + * + * This routine is mainly FOR TESTING. + * + * NOTES: + * - several registers are modified: the vector is written to VINT_STATID + * and (universe 1 chip only) the level is written to the SW_INT bits + * int VINT_MAP1 + * - NO MUTUAL EXCLUSION PROTECTION (reads VINT_EN, modifies then writes back). + * If several users need access to VINT_EN and/or VINT_STATID (and VINT_MAP1 + * on the universe 1) it is their responsibility to serialize access. + * + * Arguments: + * 'level': interrupt level, 1..7 + * 'vector': vector number (0..254) that the universe puts on the bus in response to + * an IACK cycle. NOTE: the vector number *must be even* (hardware restriction + * of the universe -- it always clears the LSB when the interrupter is + * a software interrupt). + * + * RETURNS: + * 0: Success + * -1: Invalid argument (level not 1..7, vector odd or >= 256) + * -2: Interrupt 'level' already asserted (maybe nobody handles it). + * You can manually clear it be writing the respective bit in + * VINT_STAT. Make sure really nobody responds to avoid spurious + * interrupts (consult universe docs). + */ + +int +vmeUniverseIntRaiseXX(volatile LERegister *base, int level, unsigned vector); + +int +vmeUniverseIntRaise(int level, unsigned vector); + +/* Map internal register block to VME. + * + * This routine is intended for BSP implementors. The registers can be + * made accessible from VME so that the interrupt handler can flush the + * bridge FIFO (see below). The preferred method is by accessing VME CSR, + * though, if these are mapped [and the BSP provides an outbound window]. + * On the universe we can also disable posted writes in the 'ordinary' + * outbound windows. + * + * vme_base: VME address where the universe registers (4k) can be mapped. + * This VME address must fall into a range covered by + * any pre-configured outbound window. + * address_space: The desired VME address space. + * (all of SUP/USR/PGM/DATA are always accepted). + * + * See NOTES [vmeUniverseInstallIrqMgrAlt()] below for further information. + * + * RETURNS: 0 on success, nonzero on error. It is not possible (and results + * in a non-zero return code) to change the CRG VME address after + * initializing the interrupt manager as it uses the CRG. + */ +int +vmeUniverseMapCRGXX(volatile LERegister *base, unsigned long vme_base, unsigned long address_space); + +int +vmeUniverseMapCRG(unsigned long vme_base, unsigned long address_space); + + +#ifdef __rtems__ + +/* VME Interrupt Handler functionality */ + +/* we dont use the current RTEMS/BSP interrupt API for the + * following reasons: + * + * - RTEMS/BSP API does not pass an argument to the ISR :-( :-( + * - no separate vector space for VME vectors. Some vectors would + * have to overlap with existing PCI/ISA vectors. + * - RTEMS/BSP API allocates a structure for every possible vector + * - the irq_on(), irq_off() functions add more bloat than helping. + * They are (currently) only used by the framework to disable + * interrupts at the device level before removing a handler + * and to enable interrupts after installing a handler. + * These operations may as well be done by the driver itself. + * + * Hence, we maintain our own (VME) handler table and hook our PCI + * handler into the standard RTEMS/BSP environment. Our handler then + * dispatches VME interrupts. + */ + +typedef void (*VmeUniverseISR) (void *usrArg, unsigned long vector); + +/* use these special vectors to connect a handler to the + * universe specific interrupts (such as "DMA done", + * VOWN, error irqs etc.) + * NOTE: The wrapper clears all status LINT bits (except + * for regular VME irqs). Also note that it is the user's + * responsibility to enable the necessary interrupts in + * LINT_EN + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER + * DEPENDS ON IT + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + */ +#define UNIV_VOWN_INT_VEC 256 +#define UNIV_DMA_INT_VEC 257 +#define UNIV_LERR_INT_VEC 258 +#define UNIV_VERR_INT_VEC 259 +/* 260 is reserved */ +#define UNIV_VME_SW_IACK_INT_VEC 261 +#define UNIV_PCI_SW_INT_VEC 262 +#define UNIV_SYSFAIL_INT_VEC 263 +#define UNIV_ACFAIL_INT_VEC 264 +#define UNIV_MBOX0_INT_VEC 265 +#define UNIV_MBOX1_INT_VEC 266 +#define UNIV_MBOX2_INT_VEC 267 +#define UNIV_MBOX3_INT_VEC 268 +#define UNIV_LM0_INT_VEC 269 +#define UNIV_LM1_INT_VEC 270 +#define UNIV_LM2_INT_VEC 271 +#define UNIV_LM3_INT_VEC 272 + +#define UNIV_NUM_INT_VECS 273 + + +/* install a handler for a VME vector + * RETURNS 0 on success, nonzero on failure. + */ +int +vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR handler, void *usrArg); + +/* remove a handler for a VME vector. The vector and usrArg parameters + * must match the respective parameters used when installing the handler. + * RETURNS 0 on success, nonzero on failure. + */ +int +vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR handler, void *usrArg); + +/* query for the currently installed ISR and usr parameter at a given vector + * RETURNS: ISR or 0 (vector too big or no ISR installed) + */ +VmeUniverseISR +vmeUniverseISRGet(unsigned long vector, void **parg); + +/* utility routines to enable/disable a VME IRQ level. + * + * To enable/disable the internal interrupt sources (special vectors above) + * pass a vector argument > 255. + * + * RETURNS 0 on success, nonzero on failure + */ +int +vmeUniverseIntEnable(unsigned int level); +int +vmeUniverseIntDisable(unsigned int level); + +/* Check if an interrupt level or internal source is enabled: + * + * 'level': VME level 1..7 or internal special vector > 255 + * + * RETURNS: value > 0 if interrupt is currently enabled, + * zero if interrupt is currently disabled, + * -1 on error (invalid argument). + */ +int +vmeUniverseIntIsEnabled(unsigned int level); + + +/* Change the routing of IRQ 'level' to 'pin'. + * If the BSP connects more than one of the eight + * physical interrupt lines from the universe to + * the board's PIC then you may change the physical + * line a given 'level' is using. By default, + * all 7 VME levels use the first wire (pin==0) and + * all internal sources use the (optional) second + * wire (pin==1). + * This feature is useful if you want to make use of + * different hardware priorities of the PIC. Let's + * say you want to give IRQ level 7 the highest priority. + * You could then give 'pin 0' a higher priority (at the + * PIC) and 'pin 1' a lower priority and issue. + * + * for ( i=1; i<7; i++ ) vmeUniverseIntRoute(i, 1); + * + * PARAMETERS: + * 'level' : VME interrupt level '1..7' or one of + * the internal sources. Pass the internal + * source's vector number (>=256). + * 'pin' : a value of 0 routes the requested IRQ to + * the first line registered with the manager + * (vmeIrqUnivOut parameter), a value of 1 + * routes it to the alternate wire + * (specialIrqUnivOut) + * RETURNS: 0 on success, nonzero on error (invalid arguments) + * + * NOTES: - DONT change the universe 'map' registers + * directly. The driver caches routing internally. + * - support for the 'specialIrqUnivOut' wire is + * board dependent. If the board only provides + * a single physical wire from the universe to + * the PIC then the feature might not be available. + */ +int +vmeUniverseIntRoute(unsigned int level, unsigned int pin); + +/* Loopback test of the VME interrupt subsystem. + * - installs ISRs on 'vector' and on UNIV_VME_SW_IACK_INT_VEC + * - asserts VME interrupt 'level' + * - waits for both interrupts: 'ordinary' VME interrupt of 'level' and + * IACK completion interrupt ('special' vector UNIV_VME_SW_IACK_INT_VEC). + * + * NOTES: + * - make sure no other handler responds to 'level'. + * - make sure no ISR is installed on both vectors yet. + * - ISRs installed by this routine are removed after completion. + * - no concurrent access protection of all involved resources + * (levels, vectors and registers [see vmeUniverseIntRaise()]) + * is implemented. + * - this routine is intended for TESTING (when implementing new BSPs etc.). + * - one RTEMS message queue is temporarily used (created/deleted). + * - the universe 1 always yields a zero vector (VIRQx_STATID) in response + * to a self-generated VME interrupt. As a workaround, the routine + * only accepts a zero vector when running on a universe 1. + * + * RETURNS: + * 0: Success. + * -1: Invalid arguments. + * 1: Test failed (outstanding interrupts). + * rtems_status_code: Failed RTEMS directive. + */ +int +vmeUniverseIntLoopbackTst(int level, unsigned vector); + + +/* the universe interrupt handler is capable of routing all sorts of + * (VME) interrupts to 8 different lines (some of) which may be hooked up + * in a (board specific) way to a PIC. + * + * This driver only supports at most two lines. By default, it routes the + * 7 VME interrupts to the main line and optionally, it routes the 'special' + * interrupts generated by the universe itself (DMA done, VOWN etc.) + * to a second line. If no second line is available, all IRQs are routed + * to the main line. + * + * The routing of interrupts to the two lines can be modified (using + * the vmeUniverseIntRoute() call - see above - i.e., to make use of + * different hardware priorities of the two pins. + * + * Because the driver has no way to figure out which lines are actually + * wired to the PIC, this information has to be provided when installing + * the manager. + * + * Hence the manager sets up routing VME interrupts to 1 or 2 universe + * OUTPUTS. However, it must also be told to which PIC INPUTS they + * are wired. + * Optionally, the first PIC input line can be read from PCI config space + * but the second must be passed to this routine. Note that the info read + * from PCI config space is wrong for many boards! + * + * PARAMETERS: + * vmeIrqUnivOut: to which output pin (of the universe) should the 7 + * VME irq levels be routed. + * vmeIrqPicLine: specifies to which PIC input the 'main' output is + * wired. If passed a value < 0, the driver reads this + * information from PCI config space ("IRQ line"). + * specialIrqUnivOut: to which output pin (of the universe) should the + * internally irqs be routed. Use 'vmeIRQunivOut' + * if < 0. + * specialIrqPicLine: specifies to which PIC input the 'special' output + * pin is wired. The wiring of the 'vmeIRQunivOut' to + * the PIC is determined by reading PCI config space. + * + * RETURNS: 0 on success, -1 on failure. + * + */ + +/* This routine is outside of the __INSIDE_RTEMS_BSP__ test for bwrds compatibility ONLY */ +int +vmeUniverseInstallIrqMgr(int vmeIrqUnivOut, + int vmeIrqPicLine, + int specialIrqUnivOut, + int specialIrqPicLine); + + +#if defined(__INSIDE_RTEMS_BSP__) +#include <stdarg.h> + +/* up to 4 universe outputs are now supported by this alternate + * entry point. + * Terminate the vararg list (uni_pin/pic_pin pairs) with a + * '-1' uni_pin. + * E.g., the old interface is now just a wrapper to + * vmeUniverseInstallIrqMgrAlt(0, vmeUnivOut, vmePicLint, specUnivOut, specPicLine, -1); + * + * The 'IRQ_MGR_SHARED' flag uses the BSP_install_rtems_shared_irq_handler() + * API. CAVEAT: shared interrupts need RTEMS workspace, i.e., the + * VME interrupt manager can only be installed *after workspace is initialized* + * if 'shared' is nonzero (i.e., *not* from bspstart()). + * + * If 'PW_WORKAROUND' flag is set then the interrupt manager will try to + * find a way to access the control registers from VME so that the universe's + * posted write FIFO can be flushed after the user ISR returns: + * + * The installation routine looks first for CSR registers in CSR space (this + * requires: + * - a VME64 crate with autoid or geographical addressing + * - the firmware or BSP to figure out the slot number and program the CSR base + * in the universe. + * - the BSP to open an outbound window to CSR space. + * + * If CSR registers cannot be found then the installation routine looks for CRG registers: + * - BSP must map CRG on VME + * - CRG must be visible in outbound window + * CAVEAT: multiple boards with same BSP on single backplane must not map their CRG + * to the same address! + */ + +#define VMEUNIVERSE_IRQ_MGR_FLAG_SHARED 1 /* use shared interrupts */ +#define VMEUNIVERSE_IRQ_MGR_FLAG_PW_WORKAROUND 2 /* use shared interrupts */ + +int +vmeUniverseInstallIrqMgrAlt(int flags, int uni_pin0, int pic_pin0, ...); + +int +vmeUniverseInstallIrqMgrVa(int flags, int uni_pin0, int pic_pin0, va_list ap); + +#endif /* __INSIDE_RTEMS_BSP__ */ +#endif /* __rtems__ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/vmeUniverseDMA.h b/bsps/include/bsp/vmeUniverseDMA.h new file mode 100644 index 0000000000..d0a3d6f0e7 --- /dev/null +++ b/bsps/include/bsp/vmeUniverseDMA.h @@ -0,0 +1,95 @@ +/** + * @file + * + * @ingroup shared_vmeuniversedma + * + * @brief vmeUniverseDMA Support + */ + +#ifndef VME_UNIVERSE_DMA_H +#define VME_UNIVERSE_DMA_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2006, 2007 + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 <bsp/vmeUniverse.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup shared_vmeuniversedma vmeUniverseDMA Support + * + * @ingroup shared_vmeuniverse + * + * @brief vmeUniverseDMA Support Package + */ + +extern struct VMEDmaListClassRec_ vmeUniverseDmaListClass; + +int +vmeUniverseDmaSetupXX(volatile LERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom); + +int +vmeUniverseDmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom); + +int +vmeUniverseDmaStartXX(volatile LERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes); + +int +vmeUniverseDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes); + +uint32_t +vmeUniverseDmaStatusXX(volatile LERegister *base, int channel); + +uint32_t +vmeUniverseDmaStatus(int channel); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsps/include/bsp/vme_am_defs.h b/bsps/include/bsp/vme_am_defs.h new file mode 100644 index 0000000000..efa28b3aa0 --- /dev/null +++ b/bsps/include/bsp/vme_am_defs.h @@ -0,0 +1,198 @@ +/** + * @file + * + * @ingroup shared_vmeamdefs + * + * @brief vxworks compatible addressing modes + */ + +#ifndef VME_AM_DEFINITIONS_H +#define VME_AM_DEFINITIONS_H + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2002-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software 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 + */ + +/** + * @defgroup shared_vmeamdefs VME_AM_DEFS + * + * @ingroup shared_vmeuniverse + * + * @brief 64-bit *addresses* are not supported [data are]. + */ + +#ifndef VME_AM_STD_SUP_BLT +#define VME_AM_STD_SUP_BLT 0x3f +#endif +#ifndef VME_AM_STD_SUP_ASCENDING +#define VME_AM_STD_SUP_ASCENDING 0x3f +#endif +#ifndef VME_AM_STD_SUP_PGM +#define VME_AM_STD_SUP_PGM 0x3e +#endif +#ifndef VME_AM_STD_SUP_MBLT +#define VME_AM_STD_SUP_MBLT 0x3c +#endif +#ifndef VME_AM_STD_USR_BLT +#define VME_AM_STD_USR_BLT 0x3b +#endif +#ifndef VME_AM_STD_USR_ASCENDING +#define VME_AM_STD_USR_ASCENDING 0x3b +#endif +#ifndef VME_AM_STD_USR_PGM +#define VME_AM_STD_USR_PGM 0x3a +#endif +#ifndef VME_AM_STD_SUP_DATA +#define VME_AM_STD_SUP_DATA 0x3d +#endif +#ifndef VME_AM_STD_USR_DATA +#define VME_AM_STD_USR_DATA 0x39 +#endif +#ifndef VME_AM_STD_USR_MBLT +#define VME_AM_STD_USR_MBLT 0x38 +#endif +#ifndef VME_AM_EXT_SUP_BLT +#define VME_AM_EXT_SUP_BLT 0x0f +#endif +#ifndef VME_AM_EXT_SUP_ASCENDING +#define VME_AM_EXT_SUP_ASCENDING 0x0f +#endif +#ifndef VME_AM_EXT_SUP_PGM +#define VME_AM_EXT_SUP_PGM 0x0e +#endif +#ifndef VME_AM_EXT_SUP_DATA +#define VME_AM_EXT_SUP_DATA 0x0d +#endif +#ifndef VME_AM_EXT_SUP_MBLT +#define VME_AM_EXT_SUP_MBLT 0x0c +#endif +#ifndef VME_AM_EXT_USR_BLT +#define VME_AM_EXT_USR_BLT 0x0b +#endif +#ifndef VME_AM_EXT_USR_ASCENDING +#define VME_AM_EXT_USR_ASCENDING 0x0b +#endif +#ifndef VME_AM_EXT_USR_PGM +#define VME_AM_EXT_USR_PGM 0x0a +#endif +#ifndef VME_AM_EXT_USR_DATA +#define VME_AM_EXT_USR_DATA 0x09 +#endif +#ifndef VME_AM_EXT_USR_MBLT +#define VME_AM_EXT_USR_MBLT 0x08 +#endif +#ifndef VME_AM_2eVME_6U +#define VME_AM_2eVME_6U 0x20 +#endif +#ifndef VME_AM_2eVME_3U +#define VME_AM_2eVME_3U 0x21 +#endif +#ifndef VME_AM_CSR +#define VME_AM_CSR 0x2f +#endif +#ifndef VME_AM_SUP_SHORT_IO +#define VME_AM_SUP_SHORT_IO 0x2d +#endif +#ifndef VME_AM_USR_SHORT_IO +#define VME_AM_USR_SHORT_IO 0x29 +#endif +#ifndef VME_AM_IS_SHORT +#define VME_AM_IS_SHORT(a) (((a) & 0x30) == 0x20) +#endif +#ifndef VME_AM_IS_STD +#define VME_AM_IS_STD(a) (((a) & 0x30) == 0x30) +#endif +#ifndef VME_AM_IS_EXT +#define VME_AM_IS_EXT(a) (((a) & 0x30) == 0x00) +#endif +#ifndef VME_AM_IS_SUP +#define VME_AM_IS_SUP(a) ((a) & 4) +#endif + +/* Mask for standard address modifiers */ + +#ifndef VME_AM_MASK +#define VME_AM_MASK 0x3f +#endif + +/* Hint that a window is mapping memory; the + * driver may assume it to be safe to enable decoupled + * cycles, caching and the like... + */ +#ifndef VME_AM_IS_MEMORY +#define VME_AM_IS_MEMORY (1<<8) +#endif + +/* I don't know AMs for 2eSST so we use some extra bits; + * HOWEVER: these are just qualifiers to the VME_AM_2eVME_xx modes + * i.e., if you want 2eSST you must also select 2eVME... + */ + +/* 2eSST broadcast; you still need to set one of the speed bits */ +#define VME_AM_2eSST_BCST (1<<9) +/* Low speed (driver specific) */ +#define VME_AM_2eSST_LO (1<<10) +/* Mid speed (driver specific) */ +#define VME_AM_2eSST_MID (2<<10) +/* High speed (driver specific) */ +#define VME_AM_2eSST_HI (3<<10) + +#define VME_AM_IS_2eSST(am) ((am) & (3<<10)) + +/* Use 8/16/32-bit transfers for coupled- or BLT cycles + * (MBLT, 2exxx are probably always 64-bit) + */ +#define VME_MODE_DBW_MSK (3<<12) +#define VME_MODE_DBW8 (1<<12) +#define VME_MODE_DBW16 (2<<12) +#define VME_MODE_DBW32 (3<<12) + +/* Unused Flags 1<<14 .. 1<<23 are reserved + * + * (20-23 used by DMA API). + * Flags 1<<24 .. 1<<31 are for driver specific options + */ + + +#endif |