summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/ascs/grascs.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/ascs/grascs.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/ascs/grascs.c616
1 files changed, 0 insertions, 616 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/ascs/grascs.c b/c/src/lib/libbsp/sparc/shared/ascs/grascs.c
deleted file mode 100644
index 11663b2ccc..0000000000
--- a/c/src/lib/libbsp/sparc/shared/ascs/grascs.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* This file contains the GRASCS RTEMS driver
- *
- * COPYRIGHT (c) 2008.
- * 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 <bsp.h>
-#include <ambapp.h>
-#include <bsp/grascs.h>
-
-#ifndef GAISLER_ASCS
-#define GAISLER_ASCS 0x043
-#endif
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-typedef struct {
- volatile unsigned int cmd;
- volatile unsigned int clk;
- volatile unsigned int sts;
- volatile unsigned int tcd;
- volatile unsigned int tmd;
-} GRASCS_regs;
-
-typedef struct {
- unsigned char tmconf;
- unsigned char usconf;
- unsigned char nslaves;
- unsigned char dbits;
- int clkfreq;
-} GRASCS_caps;
-
-typedef struct {
- GRASCS_regs *regs; /* Pointer to core registers */
- GRASCS_caps *caps; /* Pointer to capability struct */
- rtems_id tcsem1, tcsem2;
- rtems_id tmsem1, tmsem2;
- volatile char running;
- int tcptr;
- int tmptr;
- int tcwords;
- int tmwords;
-} GRASCS_cfg;
-
-static GRASCS_cfg *cfg = NULL;
-
-/*------------------------------------*/
-/* Start of internal helper functions */
-/*------------------------------------*/
-
-/* Function: ASCS_getaddr
- Arguments: base: Core's register base address
- irq: Core's irq
- Return values: 0 if successful, -1 if core is not found
- Description: Assigns core's register base address and
- irq to arguments. Uses AMBA plug and play to find the
- core.
-*/
-static int ASCS_get_addr(int *base, int *irq) {
-
- struct ambapp_apb_info core;
-
- if(ambapp_find_apbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_ASCS, &core) == 1) {
- *base = core.start;
- *irq = core.irq;
- DBG("ASCS_get_addr: Registerd ASCS core at 0x%x with irq %i\n",core.start, core.irq);
- return 0;
- }
- DBG("ASCS_get_addr: Failed to detect core\n");
- return -1;
-}
-
-/* Function: ASCS_calc_clkreg
- Arguments: sysfreq: System clock frequency in kHz
- etrfreq: ETR frequency in Hz
- Return values: Value of core's CLK-register
- Description: Calculates value of core's CLK-register. See
- GRASCS IP core documentation for details.
-*/
-static int ASCS_calc_clkreg(int sysfreq, int etrfreq) {
-
- if(cfg->caps->usconf)
- return 1000000/etrfreq;
- else
- return sysfreq*1000/etrfreq;
-}
-
-/* Function: ASCS_get_sysfreq
- Arguments: -
- Return values: System clock frequency in kHz, -1 if failed
- Description: Uses AMBA plug and play to lookup system frequency
-*/
-static int ASCS_get_sysfreq(void) {
-
- struct ambapp_apb_info gpt;
- struct gptimer_regs *tregs;
- int tmp;
-
- if(ambapp_find_apbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER, &gpt) == 1) {
- tregs = (struct gptimer_regs *) gpt.start;
- tmp = (tregs->scaler_reload + 1)*1000;
- DBG("ASCS_get_sysfreq: Detected system frequency %i kHz\n",tmp);
- if((tmp < GRASCS_MIN_SFREQ) || (tmp > GRASCS_MAX_SFREQ)) {
- DBG("ASCS_get_sysfreq: System frequency is invalid for ASCS core\n");
- return -1;
- }
- else
- return (tregs->scaler_reload + 1)*1000;
- }
- DBG("ASCS_get_sysfreq: Failed to detect system frequency\n");
- return -1;
-}
-
-/* Function: ASCS_irqhandler
- Arguments: v: not used
- Return values: -
- Description: Determines the source of the interrupt, clears the
- appropriate bits in the core's STS register and releases
- the associated semaphore
-*/
-static rtems_isr ASCS_irqhandler(rtems_vector_number v) {
-
- if(cfg->regs->sts & GRASCS_STS_TCDONE) {
- /* Clear TC done bit */
- cfg->regs->sts |= GRASCS_STS_TCDONE;
-
- if(--cfg->tcwords == 0)
- /* No more TCs to perform right now */
- rtems_semaphore_release(cfg->tcsem2);
- else {
- /* Block not sent yet, start next TC */
- if(cfg->caps->dbits == 8) {
- cfg->tcptr++;
- cfg->regs->tcd = *((unsigned char*)cfg->tcptr);
- }
- else if(cfg->caps->dbits == 16) {
- cfg->tcptr += 2;
- cfg->regs->tcd = *((unsigned short int*)cfg->tcptr);
- }
- else {
- cfg->tcptr += 4;
- cfg->regs->tcd = *((unsigned int*)cfg->tcptr);
- }
- }
- }
-
- if(cfg->regs->sts & GRASCS_STS_TMDONE) {
- /* Clear TM done bit */
- cfg->regs->sts |= GRASCS_STS_TMDONE;
-
- /* Store received data */
- if(cfg->caps->dbits == 8) {
- *((unsigned char*)cfg->tmptr) = (unsigned char)(cfg->regs->tmd & 0xFF);
- cfg->tmptr++;
- }
- else if(cfg->caps->dbits == 16) {
- *((unsigned short int*)cfg->tmptr) = (unsigned short int)(cfg->regs->tmd & 0xFFFF);
- cfg->tmptr += 2;
- }
- else {
- *((unsigned int*)cfg->tmptr) = cfg->regs->tmd;
- cfg->tmptr += 4;
- }
-
- if(--cfg->tmwords == 0)
- /* No more TMs to perform right now */
- rtems_semaphore_release(cfg->tmsem2);
- else
- /* Block not received yet, start next TM */
- cfg->regs->cmd |= GRASCS_CMD_SENDTM;
- }
-}
-
-/*---------------------------*/
-/* Start of driver interface */
-/*---------------------------*/
-
-/* Function: ASCS_init
- Arguments: -
- Return values: 0 if successful, -1 if unsuccessful
- Description: Initializes the ASCS core
-*/
-int ASCS_init(void) {
-
- int base, irq, tmp;
-
- DBG("ASCS_init: Starting initialization of ASCS core\n");
-
- /* Allocate memory for config, status and capability struct */
- if((cfg = (GRASCS_cfg*)malloc(sizeof(GRASCS_cfg))) == NULL) {
- DBG("ASCS_init: Could not allocate memory for cfg struc\n");
- return -1;
- }
-
- if((cfg->caps = (GRASCS_caps*)calloc(1,sizeof(GRASCS_caps))) == NULL) {
- DBG("ASCS_init: Could not allocate memory for caps struc\n");
- goto init_error1;
- }
-
- /* Create semaphores for blocking ASCS_TC/TM functions */
- if(rtems_semaphore_create(rtems_build_name('A','S','C','0'),1,
- (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
- RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
- RTEMS_NO_PRIORITY_CEILING), 0,
- &cfg->tcsem1) != RTEMS_SUCCESSFUL) {
- DBG("ASCS_init: Failed to create semaphore ASC0\n");
- goto init_error2;
- }
- if(rtems_semaphore_create(rtems_build_name('A','S','C','1'),1,
- (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
- RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
- RTEMS_NO_PRIORITY_CEILING), 0,
- &cfg->tmsem1) != RTEMS_SUCCESSFUL) {
- DBG("ASCS_init: Failed to create semaphore ASC1\n");
- goto init_error2;
- }
- /* Create semaphores for waiting on ASCS_TC/TM interrupt */
- if(rtems_semaphore_create(rtems_build_name('A','S','C','2'),0,
- (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
- RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
- RTEMS_NO_PRIORITY_CEILING), 0,
- &cfg->tcsem2) != RTEMS_SUCCESSFUL) {
- DBG("ASCS_init: Failed to create semaphore ASC2\n");
- goto init_error2;
- }
- if(rtems_semaphore_create(rtems_build_name('A','S','C','3'),0,
- (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|
- RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|
- RTEMS_NO_PRIORITY_CEILING), 0,
- &cfg->tmsem2) != RTEMS_SUCCESSFUL) {
- DBG("ASCS_init: Failed to create semaphore ASC3\n");
- goto init_error2;
- }
-
- /* Set pointer to core registers */
- if(ASCS_get_addr(&base, &irq) == -1)
- goto init_error2;
-
- cfg->regs = (GRASCS_regs*)base;
-
- /* Read core capabilities */
- tmp = cfg->regs->sts;
- cfg->caps->dbits = ((tmp >> GRASCS_STS_DBITS_BITS) & 0x1F) + 1;
- cfg->caps->nslaves = ((tmp >> GRASCS_STS_NSLAVES_BITS) & 0xF) + 1;
- cfg->caps->tmconf = (tmp >> GRASCS_STS_TMCONF_BITS) & 0x1;
- cfg->caps->usconf = (tmp >> GRASCS_STS_USCONF_BITS) & 0x1;
-
- /* Reset and configure core */
- cfg->running = 0;
- cfg->regs->cmd |= GRASCS_CMD_RESET;
- if((tmp = ASCS_get_sysfreq()) == -1)
- goto init_error2;
- cfg->caps->clkfreq = tmp;
- while(ASCS_iface_status())
- ;
- cfg->regs->clk = ASCS_calc_clkreg(tmp, GRASCS_DEFAULT_ETRFREQ);
- cfg->regs->cmd = GRASCS_CMD_US1C;
- cfg->regs->cmd |= (tmp/1000 << GRASCS_CMD_US1_BITS) | GRASCS_CMD_US1C |
- GRASCS_CMD_TCDONE | GRASCS_CMD_TMDONE;
-
- /* Register interrupt routine */
- set_vector(ASCS_irqhandler,irq+0x10,2);
-
- return 0;
-
- init_error2:
- free(cfg->caps);
- init_error1:
- free(cfg);
- return -1;
-}
-
-/* Function: ASCS_input_select
- Arguments: slave: The number of the slave that is active,
- numbered from 0-15
- Return values: 0 if successful, -GRASCS_ERROR_CAPFAULT if slave value
- is negative or too big, -GRASCS_ERROR_TRANSACTIVE if
- a TM is active.
- Description: Sets the slave_sel bits in the core's CMD register.
- they are used to choose which slave the core listens
- to when performing a TM. The bits can't be set
- during a TM, and the function will in such a case fail.
-*/
-int ASCS_input_select(int slave) {
-
- if((slave < 0) || (slave > cfg->caps->nslaves)) {
- /* Slave number is negative or too big */
- DBG("ASCS_input_select: Wrong slave number\n");
- return -GRASCS_ERROR_CAPFAULT;
- }
-
- if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
- RTEMS_SUCCESSFUL) {
- /* Can't change active slave during a TM */
- DBG("ASCS_input_select: Transaction active\n");
- return -GRASCS_ERROR_TRANSACTIVE;
- }
-
- cfg->regs->cmd = ((cfg->regs->cmd &= ~GRASCS_CMD_SLAVESEL) |
- (slave << GRASCS_CMD_SLAVESEL_BITS));
-
- rtems_semaphore_release(cfg->tmsem1);
- return 0;
-}
-
-/* Function: ASCS_etr_select
- Arguments: src: The source of the ETR signal, valid values are
- 0-GRASCS_MAX_TMS (0 = internal source, 1-GRASCS_MAX_TMS =
- external time markers 1-GRASCS_MAX_TMS).
- freq: ETR frequency in Hz. Valid values are
- GRASCS_MIN_ETRFREQ-GRASCS_MAX_ETRFREQ
- Return values: 0 if successful, -GRASCS_ERROR_CAPFAULT if src or freq values
- are invalid, -GRASCS_ERROR_STARTSTOP if synchronization interface
- isn't stopped.
- Description: Changes the source for the ETR signal. The frequency of source signal
- is assumed to be the same as the frequency of the freq input
-*/
-int ASCS_etr_select(int etr, int freq) {
-
- if((etr < 0) || (etr > GRASCS_MAX_TMS) || ((cfg->caps->tmconf == 0) && (etr > 0)) ||
- (freq < GRASCS_MIN_ETRFREQ) || (freq > GRASCS_MAX_ETRFREQ)) {
- /* ETR source value or frequency is invalid */
- DBG("ASCS_etr_select: Wrong etr src number or wrong frequency\n");
- return -GRASCS_ERROR_CAPFAULT;
- }
-
- if(cfg->regs->sts & GRASCS_STS_ERUNNING) {
- /* Synchronization interface is running */
- DBG("ASCS_etr_select: Synch interface is running\n");
- return -GRASCS_ERROR_STARTSTOP;
- }
-
- cfg->regs->clk = ASCS_calc_clkreg(cfg->caps->clkfreq,freq);
- cfg->regs->cmd = ((cfg->regs->cmd &= ~GRASCS_CMD_ETRCTRL) |
- (etr << GRASCS_CMD_ETRCTRL_BITS));
-
- return 0;
-}
-
-/* Function: ASCS_start
- Arguments: -
- Return values: -
- Description: Enables the serial interface.
-*/
-void ASCS_start(void) {
-
- /* Set register and internal status to running */
- cfg->regs->cmd |= GRASCS_CMD_STARTSTOP;
- cfg->running = 1;
-}
-
-/* Function: ASCS_stop
- Arguments: -
- Return values: -
- Description: Disables the serial interface. This function will
- block until possible calls to TC_send(_block) and
- TM_recv(_block) has returned in order to be sure
- that started transactions will be performed.
-*/
-void ASCS_stop(void) {
-
- /* Set internal status to stopped */
- cfg->running = 0;
-
- /* Obtain semaphores to avoid possible situation where a
- TC_send(_block) or TM_recv(_block) is aborted and driver is
- waiting forever for an interrupt */
- rtems_semaphore_obtain(cfg->tcsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
- rtems_semaphore_obtain(cfg->tmsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
-
- /* Change actual register value */
- cfg->regs->cmd &= ~GRASCS_CMD_STARTSTOP;
-
- /* Release the semaphores */
- rtems_semaphore_release(cfg->tcsem1);
- rtems_semaphore_release(cfg->tmsem1);
-}
-
-/* Function: ASCS_iface_status
- Arguments: -
- Return values: 0 if both serial interface and synch interface is stopped,
- 1 if serial interface is running buth synch interface is
- stopped, 2 if serial interface is stopped but synch interface
- is running, 3 if both serial and synch interface is running
- Description: Reads the core's STS register and reports the status of the
- serial and synch interfaces
-*/
-int ASCS_iface_status(void) {
-
- return ((cfg->regs->sts & 0x3) & (0x2 | cfg->running));
-}
-
-/* Function: ASCS_TC_send
- Arguments: word: Pointer to a word that should be sent
- Return values: 0 on success
- -GRASCS_ERROR_STARTSTOP if serial interface is stopped,
- -GRASCS_ERROR_TRANSACTIVE if another TC is in progress.
- Description: Start a TC and sends the data that word points to.
-*/
-int ASCS_TC_send(int *word) {
-
- int retval;
-
- if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
- RTEMS_SUCCESSFUL) {
- /* Can't start a TC_send if another TC_send of TC_send_block is
- in progress */
- DBG("ASCS_TC_send: Could not obtain semaphore, transcation probably in progress\n");
- return -GRASCS_ERROR_TRANSACTIVE;
- }
-
- if(!cfg->running) {
- /* Can't start a TC if serial interface isn't started */
- DBG("ASCS_TC_send: Serial interface is not started\n");
- retval = -GRASCS_ERROR_STARTSTOP;
- }
- else {
- /* Start the transfer */
- cfg->tcwords = 1;
- if(cfg->caps->dbits == 8)
- cfg->regs->tcd = *((unsigned char*)word);
- else if(cfg->caps->dbits == 16)
- cfg->regs->tcd = *((unsigned short int*)((int)word & ~1));
- else
- cfg->regs->tcd = *((unsigned int*)((int)word & ~3));
-
- /* Wait until transfer is complete */
- rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
- retval = 0;
- }
-
- rtems_semaphore_release(cfg->tcsem1);
-
- return retval;
-}
-
-/* Function: ASCS_TC_send_block
- Arguments: block: Pointer to the start of a datablock that
- should be sent.
- ntrans: Number of transfers needed to transfer
- the block.
- Return values: 0 if successfull, -GRASCS_ERROR_STARTSTOP if TC
- couldn't be started because serial interface is
- stopped, -GRASCS_ERROR_TRANSACTIVE if TC couldn't
- be started because another TC isn't done yet.
- Description: Starts ntrans TCs and sends the data that starts at the
- address that block points to. The size of each
- transaction will vary depending on whether the core is
- configured for 8, 16, or 32 bits data transfers.
-*/
-int ASCS_TC_send_block(int *block, int ntrans) {
-
- int retval;
-
- if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
- RTEMS_SUCCESSFUL) {
- /* Can't start a TC_send_block if another TC_send of TC_send_block is
- in progress */
- DBG("ASCS_TC_send_block: Could not obtain semaphore, transcation probably in progress\n");
- return -GRASCS_ERROR_TRANSACTIVE;
- }
-
- if(!cfg->running) {
- /* Can't start a TC if serial interface isn't started */
- DBG("ASCS_TC_send_block: Serial interface is not started\n");
- retval = -GRASCS_ERROR_STARTSTOP;
- }
- else {
- /* Start the first transfer */
- cfg->tcwords = ntrans;
- if(cfg->caps->dbits == 8) {
- cfg->tcptr = (int)block;
- cfg->regs->tcd = *((unsigned char*)cfg->tcptr);
- }
- else if(cfg->caps->dbits == 16) {
- cfg->tcptr = (int)block & ~1;
- cfg->regs->tcd = *((unsigned short int*)cfg->tcptr);
- }
- else {
- cfg->tcptr = (int)block & ~3;
- cfg->regs->tcd = *((unsigned int*)cfg->tcptr);
- }
-
- /* Wait until all transfers are complete */
- rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
- retval = 0;
- }
-
- rtems_semaphore_release(cfg->tcsem1);
-
- return retval;
-}
-
-/* Function: ASCS_TC_sync_start
- Arguments: -
- Return values: -
- Description: Starts synchronization interface. Might
- be delayed if a TM is in progress. SW can poll
- ASCS_iface_status() to find out when synch interface is
- started. First ETR pulse can be delay up to one ETR
- period depending on the source of the ETR and
- activity on the TM line.
-*/
-void ASCS_TC_sync_start(void) {
-
- cfg->regs->cmd |= GRASCS_CMD_ESTARTSTOP;
-}
-
-/* Function: ASCS_TC_sync_stop
- Arguments: -
- Return values: -
- Description: Stops the synchronization interface. Might
- be delayed for 1 us if a ETR pulse is being generated. SW
- can determine when synch interface has stopped by polling
- ASCS_iface_status().
-*/
-void ASCS_TC_sync_stop(void) {
-
- cfg->regs->cmd &= ~GRASCS_CMD_ESTARTSTOP;
-}
-
-/* Function: ASCS_TM_recv
- Arguments: word: Pointer to where the received word should be
- placed
- Return values: 0 if successful, -GRASCS_ERROR_STARTSTOP if serial
- interface isn't started, -GRASCS_ERROR_TRANSACTIVE
- if another TM is in progress
- Description: Starts a TM and stores the incoming data in word.
-*/
-int ASCS_TM_recv(int *word) {
-
- int retval;
-
- if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
- RTEMS_SUCCESSFUL) {
- /* Can't start a TM_recv if another TM_recv of TM_recv_block is
- in progress */
- DBG("ASCS_TM_recv: Could not obtain semaphore, transaction probably in progress\n");
- return -GRASCS_ERROR_TRANSACTIVE;
- }
-
- if(!cfg->running) {
- /* Can't start a TM if serial interface isn't started */
- DBG("ASCS_TM_recv: Serial interface is not started\n");
- retval = -GRASCS_ERROR_STARTSTOP;
- }
- else {
- /* Start transfer */
- cfg->tmwords = 1;
- cfg->tmptr = (int)word;
- cfg->regs->cmd |= GRASCS_CMD_SENDTM;
-
- /* Wait until transfer finishes */
- rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
- retval = 0;
- }
-
- rtems_semaphore_release(cfg->tmsem1);
-
- return retval;
-}
-
-/* Function: ASCS_TM_recv_block
- Arguments: block: Pointer to where the received datablock
- should be stored.
- ntrans: Number of transfers needed to transfer
- the block.
- Return values: 0 if successful, -GRASCS_ERROR_STARTSTOP if serial
- interface isn't started, -GRASCS_ERROR_TRANSACTIVE if
- a performed TM hasn't been processed yet
- Description: Starts ntrans TMs and stores the data at the address
- that block points to. The size of each transaction
- will vary depending on whether the core is
- configured for 8, 16, or 32 bits data transfers.
-*/
-int ASCS_TM_recv_block(int *block, int ntrans) {
-
- int retval;
-
- if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) !=
- RTEMS_SUCCESSFUL) {
- /* Can't start a TM_recv_block if another TM_recv of TM_recv_block is
- in progress */
- DBG("ASCS_TM_recv_block: Could not obtain semaphore, transaction probably in progress\n");
- return -GRASCS_ERROR_TRANSACTIVE;
- }
-
- if(!cfg->running) {
- /* Can't start a TM if serial interface isn't started */
- DBG("ASCS_TM_recv_block: Serial interface is not started\n");
- retval = -GRASCS_ERROR_STARTSTOP;
- }
- else {
- /* Start transfer */
- cfg->tmwords = ntrans;
- cfg->tmptr = (int)block;
- cfg->regs->cmd |= GRASCS_CMD_SENDTM;
-
- /* Wait until transfer finishes */
- rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
- retval = 0;
- }
-
- rtems_semaphore_release(cfg->tmsem1);
-
- return retval;
-}