diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c | 544 |
1 files changed, 0 insertions, 544 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c deleted file mode 100644 index d63983bda9..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c +++ /dev/null @@ -1,544 +0,0 @@ -/* GR1553B BM driver - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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. - */ - -#include <stdlib.h> -#include <string.h> -#include <drvmgr/drvmgr.h> -#include <drvmgr/ambapp_bus.h> - -#include <bsp/gr1553b.h> -#include <bsp/gr1553bm.h> - - -#define GR1553BM_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BM_READ_MEM(adr) (*(volatile uint32_t *)(adr)) - -#define GR1553BM_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BM_READ_REG(adr) (*(volatile uint32_t *)(adr)) - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) -#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) -#define SPIN_FREE(lock) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -struct gr1553bm_priv { - struct drvmgr_dev **pdev; - struct gr1553b_regs *regs; - SPIN_DECLARE(devlock); - - void *buffer; - unsigned int buffer_base_hw; - unsigned int buffer_base; - unsigned int buffer_end; - unsigned int buffer_size; - unsigned int read_pos; - int started; - struct gr1553bm_config cfg; - - /* Time updated by IRQ when 24-bit Time counter overflows */ - volatile uint64_t time; -}; - -void gr1553bm_isr(void *data); - -/* Default Driver configuration */ -struct gr1553bm_config gr1553bm_default_config = -{ - /* Highest resolution, use Time overflow IRQ to track */ - .time_resolution = 0, - .time_ovf_irq = 1, - - /* No filtering, log all */ - .filt_error_options = GR1553BM_ERROPTS_ALL, - .filt_rtadr = 0xffffffff, - .filt_subadr = 0xffffffff, - .filt_mc = 0x0007ffff, - - /* 128Kbyte dynamically allocated buffer. */ - .buffer_size = 128*1024, - .buffer_custom = NULL, -}; - -void gr1553bm_register(void) -{ - /* The BM driver rely on the GR1553B Driver */ - gr1553_register(); -} - -static void gr1553bm_hw_start(struct gr1553bm_priv *priv) -{ - SPIN_IRQFLAGS(irqflags); - - /* Enable IRQ source and mark running state */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - priv->started = 1; - - /* Clear old IRQ flags */ - priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF; - - /* Unmask IRQ sources */ - if ( priv->cfg.time_ovf_irq ) { - priv->regs->imask |= GR1553B_IRQEN_BMDE | GR1553B_IRQEN_BMTOE; - } else { - priv->regs->imask |= GR1553B_IRQEN_BMDE; - } - - /* Start logging */ - priv->regs->bm_ctrl = - (priv->cfg.filt_error_options & - (GR1553B_BM_CTRL_MANL|GR1553B_BM_CTRL_UDWL|GR1553B_BM_CTRL_IMCL)) - | GR1553B_BM_CTRL_BMEN; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -static void gr1553bm_hw_stop(struct gr1553bm_priv *priv) -{ - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Stop Logging */ - priv->regs->bm_ctrl = 0; - - /* Stop IRQ source */ - priv->regs->imask &= ~(GR1553B_IRQEN_BMDE|GR1553B_IRQEN_BMTOE); - - /* Clear IRQ flags */ - priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF; - - priv->started = 0; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -/* Open device by number */ -void *gr1553bm_open(int minor) -{ - struct drvmgr_dev **pdev = NULL; - struct gr1553bm_priv *priv = NULL; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Allocate requested device */ - pdev = gr1553_bm_open(minor); - if ( pdev == NULL ) - goto fail; - - priv = malloc(sizeof(struct gr1553bm_priv)); - if ( priv == NULL ) - goto fail; - memset(priv, 0, sizeof(struct gr1553bm_priv)); - - /* Init BC device */ - priv->pdev = pdev; - (*pdev)->priv = priv; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)(*pdev)->businfo; - pnpinfo = &ambadev->info; - priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - SPIN_INIT(&priv->devlock, "gr1553bm"); - - /* Start with default configuration */ - priv->cfg = gr1553bm_default_config; - - /* Unmask IRQs */ - gr1553bm_hw_stop(priv); - - return priv; - -fail: - if ( pdev ) - gr1553_bm_close(pdev); - if ( priv ) - free(priv); - return NULL; -} - -/* Close previously */ -void gr1553bm_close(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) { - gr1553bm_stop(bm); - } - - if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) - free(priv->buffer); - - gr1553_bm_close(priv->pdev); - free(priv); -} - -/* Configure the BM driver */ -int gr1553bm_config(void *bm, struct gr1553bm_config *cfg) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) - return -1; - - /* Check Config validity? */ -/*#warning IMPLEMENT.*/ - - /* Free old buffer if dynamically allocated */ - if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) { - free(priv->buffer); - priv->buffer = NULL; - } - priv->buffer_size = cfg->buffer_size & ~0x7; /* on 8 byte bounadry */ - if ((unsigned int)cfg->buffer_custom & 1) { - /* Custom Address Given in Remote address. We need - * to convert it intoTranslate into Hardware a - * hardware accessible address - */ - priv->buffer_base_hw = (unsigned int)cfg->buffer_custom & ~1; - priv->buffer = cfg->buffer_custom; - drvmgr_translate_check( - *priv->pdev, - DMAMEM_TO_CPU, - (void *)priv->buffer_base_hw, - (void **)&priv->buffer_base, - priv->buffer_size); - } else { - if (cfg->buffer_custom == NULL) { - /* Allocate new buffer dynamically */ - priv->buffer = malloc(priv->buffer_size + 8); - if (priv->buffer == NULL) - return -1; - } else { - /* Address given in CPU accessible address, no - * translation required. - */ - priv->buffer = cfg->buffer_custom; - } - /* Align to 16 bytes */ - priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) & - ~(8-1); - /* Translate address of buffer base into address that Hardware must - * use to access the buffer. - */ - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->buffer_base, - (void **)&priv->buffer_base_hw, - priv->buffer_size); - - } - - /* Copy valid config */ - priv->cfg = *cfg; - - return 0; -} - -/* Start logging */ -int gr1553bm_start(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) - return -1; - if ( priv->buffer == NULL ) - return -2; - - /* Start at Time = 0 */ - priv->regs->bm_ttag = - priv->cfg.time_resolution << GR1553B_BM_TTAG_RES_BIT; - - /* Configure Filters */ - priv->regs->bm_adr = priv->cfg.filt_rtadr; - priv->regs->bm_subadr = priv->cfg.filt_subadr; - priv->regs->bm_mc = priv->cfg.filt_mc; - - /* Set up buffer */ - priv->regs->bm_start = priv->buffer_base_hw; - priv->regs->bm_end = priv->buffer_base_hw + priv->cfg.buffer_size - 4; - priv->regs->bm_pos = priv->buffer_base_hw; - priv->read_pos = priv->buffer_base; - priv->buffer_end = priv->buffer_base + priv->cfg.buffer_size; - - /* Register ISR handler and unmask IRQ source at IRQ controller */ - if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bm", gr1553bm_isr, priv)) - return -3; - - /* Start hardware and set priv->started */ - gr1553bm_hw_start(priv); - - return 0; -} - -/* Stop logging */ -void gr1553bm_stop(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - /* Stop Hardware */ - gr1553bm_hw_stop(priv); - - /* At this point the hardware must be stopped and IRQ - * sources unmasked. - */ - - /* Unregister ISR handler and unmask 1553 IRQ source at IRQ ctrl */ - drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bm_isr, priv); -} - -int gr1553bm_started(void *bm) -{ - return ((struct gr1553bm_priv *)bm)->started; -} - -/* Get 64-bit 1553 Time. - * - * Update software time counters and return the current time. - */ -void gr1553bm_time(void *bm, uint64_t *time) -{ - struct gr1553bm_priv *priv = bm; - unsigned int hwtime, hwtime2; - -resample: - if ( priv->started && (priv->cfg.time_ovf_irq == 0) ) { - /* Update Time overflow counter. The carry bit from Time counter - * is located in IRQ Flag. - * - * When IRQ is not used this function must be called often - * enough to avoid that the Time overflows and the carry - * bit is already set. The frequency depends on the Time - * resolution. - */ - if ( priv->regs->irq & GR1553B_IRQ_BMTOF ) { - /* Clear carry bit */ - priv->regs->irq = GR1553B_IRQ_BMTOF; - priv->time += (GR1553B_BM_TTAG_VAL + 1); - } - } - - /* Report current Time, even if stopped */ - hwtime = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL; - if ( time ) - *time = priv->time | hwtime; - - if ( priv->cfg.time_ovf_irq ) { - /* Detect wrap around */ - hwtime2 = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL; - if ( hwtime > hwtime2 ) { - /* priv->time and hwtime may be out of sync if - * IRQ updated priv->time just after bm_ttag was read - * here, we resample if we detect inconsistancy. - */ - goto resample; - } - } -} - -/* Number of entries available in DMA buffer */ -int gr1553bm_available(void *bm, int *nentries) -{ - struct gr1553bm_priv *priv = bm; - unsigned int top, bot, pos; - - if ( !priv->started ) - return -1; - - /* Get BM posistion in log */ - pos = priv->regs->bm_pos; - - /* Convert into CPU accessible address */ - pos = priv->buffer_base + (pos - priv->buffer_base_hw); - - if ( pos >= priv->read_pos ) { - top = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry); - bot = 0; - } else { - top = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry); - bot = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry); - } - - if ( nentries ) - *nentries = top+bot; - - return 0; -} - -/* Read a maximum number of entries from LOG buffer. */ -int gr1553bm_read(void *bm, struct gr1553bm_entry *dst, int *max) -{ - struct gr1553bm_priv *priv = bm; - unsigned int dest, pos, left, newPos, len; - unsigned int topAdr, botAdr, topLen, botLen; - - if ( !priv || !priv->started ) - return -1; - - left = *max; - pos = priv->regs->bm_pos & ~0x7; - - /* Convert into CPU accessible address */ - pos = priv->buffer_base + (pos - priv->buffer_base_hw); - - if ( (pos == priv->read_pos) || (left < 1) ) { - /* No data available */ - *max = 0; - return 0; - } - newPos = 0; - - /* Addresses and lengths of BM log buffer */ - if ( pos >= priv->read_pos ) { - /* Read Top only */ - topAdr = priv->read_pos; - botAdr = 0; - topLen = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry); - botLen = 0; - } else { - /* Read Top and Bottom */ - topAdr = priv->read_pos; - botAdr = priv->buffer_base; - topLen = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry); - botLen = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry); - } - - dest = (unsigned int)dst; - if ( topLen > 0 ) { - /* Copy from top area first */ - if ( topLen > left ) { - len = left; - left = 0; - } else { - len = topLen; - left -= topLen; - } - newPos = topAdr + (len * sizeof(struct gr1553bm_entry)); - if ( newPos >= priv->buffer_end ) - newPos -= priv->buffer_size; - if ( priv->cfg.copy_func ) { - dest += priv->cfg.copy_func( - dest, /*Optional Destination*/ - (void *)topAdr, /* DMA start address */ - len, /* Number of entries */ - priv->cfg.copy_func_arg /* Custom ARG */ - ); - } else { - memcpy( (void *)dest, - (void *)topAdr, - len * sizeof(struct gr1553bm_entry)); - dest += len * sizeof(struct gr1553bm_entry); - } - } - - if ( (botLen > 0) && (left > 0) ) { - /* Copy bottom area last */ - if ( botLen > left ) { - len = left; - left = 0; - } else { - len = botLen; - left -= botLen; - } - newPos = botAdr + (len * sizeof(struct gr1553bm_entry)); - - if ( priv->cfg.copy_func ) { - priv->cfg.copy_func( - dest, /*Optional Destination*/ - (void *)botAdr, /* DMA start address */ - len, /* Number of entries */ - priv->cfg.copy_func_arg /* Custom ARG */ - ); - } else { - memcpy( (void *)dest, - (void *)botAdr, - len * sizeof(struct gr1553bm_entry)); - } - } - - /* Remember last read posistion in buffer */ - /*printf("New pos: 0x%08x (0x%08x), %d\n", newPos, priv->read_pos, *max - left);*/ - priv->read_pos = newPos; - - /* Return number of entries read */ - *max = *max - left; - - return 0; -} - -/* Note: This is a shared interrupt handler, with BC/RT driver - * we must determine the cause of IRQ before handling it. - */ -void gr1553bm_isr(void *data) -{ - struct gr1553bm_priv *priv = data; - uint32_t irqflag; - - /* Get Causes */ - irqflag = priv->regs->irq & (GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF); - - /* Check spurious IRQs */ - if ( (irqflag == 0) || (priv->started == 0) ) - return; - - if ( (irqflag & GR1553B_IRQ_BMTOF) && priv->cfg.time_ovf_irq ) { - /* 1553 Time Over flow. Time is 24-bits */ - priv->time += (GR1553B_BM_TTAG_VAL + 1); - - /* Clear cause handled */ - priv->regs->irq = GR1553B_IRQ_BMTOF; - } - - if ( irqflag & GR1553B_IRQ_BMD ) { - /* BM DMA ERROR. Fatal error, we stop BM hardware and let - * user take care of it. From now on all calls will result - * in an error because the BM is stopped (priv->started=0). - */ - - /* Clear cause handled */ - priv->regs->irq = GR1553B_IRQ_BMD; - - if ( priv->cfg.dma_error_isr ) - priv->cfg.dma_error_isr(data, priv->cfg.dma_error_arg); - - gr1553bm_hw_stop(priv); - } -} |