diff options
Diffstat (limited to 'bsps/shared/grlib/can/grcan.c')
-rw-r--r-- | bsps/shared/grlib/can/grcan.c | 719 |
1 files changed, 78 insertions, 641 deletions
diff --git a/bsps/shared/grlib/can/grcan.c b/bsps/shared/grlib/can/grcan.c index d69d99d85a..69f64cc285 100644 --- a/bsps/shared/grlib/can/grcan.c +++ b/bsps/shared/grlib/can/grcan.c @@ -1,7 +1,7 @@ /* * GRCAN driver * - * COPYRIGHT (c) 2007. + * COPYRIGHT (c) 2007-2019. * Cobham Gaisler AB. * * The license and distribution terms for this file may be @@ -18,18 +18,17 @@ #include <rtems/bspIo.h> #include <grlib/grcan.h> +#include <grlib/canbtrs.h> #include <drvmgr/drvmgr.h> #include <grlib/ambapp_bus.h> #include <grlib/ambapp.h> #include <grlib/grlib_impl.h> +#include "grcan_internal.h" /* Maximum number of GRCAN devices supported by driver */ #define GRCAN_COUNT_MAX 8 -#define WRAP_AROUND_TX_MSGS 1 -#define WRAP_AROUND_RX_MSGS 2 -#define GRCAN_MSG_SIZE sizeof(struct grcan_msg) #define BLOCK_SIZE (16*4) /* grcan needs to have it buffers aligned to 1k boundaries */ @@ -57,15 +56,6 @@ #define IRQ_MASK(irqno) #endif -#ifndef GRCAN_DEFAULT_BAUD - /* default to 500kbits/s */ - #define GRCAN_DEFAULT_BAUD 500000 -#endif - -#ifndef GRCAN_SAMPLING_POINT - #define GRCAN_SAMPLING_POINT 80 -#endif - /* Uncomment for debug output */ /****************** DEBUG Definitions ********************/ #define DBG_TX 2 @@ -88,70 +78,10 @@ int state2err[4] = { /* STATE_AHBERR */ GRCAN_RET_AHBERR }; -struct grcan_msg { - unsigned int head[2]; - unsigned char data[8]; -}; - -struct grcan_config { - struct grcan_timing timing; - struct grcan_selection selection; - int abort; - int silent; -}; - -struct grcan_priv { - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; /* Device Name */ - unsigned int baseaddr, ram_base; - struct grcan_regs *regs; - int irq; - int minor; - int open; - int started; - unsigned int channel; - int flushing; - unsigned int corefreq_hz; - - /* Circular DMA buffers */ - void *_rx, *_rx_hw; - void *_tx, *_tx_hw; - void *txbuf_adr; - void *rxbuf_adr; - struct grcan_msg *rx; - struct grcan_msg *tx; - unsigned int rxbuf_size; /* requested RX buf size in bytes */ - unsigned int txbuf_size; /* requested TX buf size in bytes */ - - int txblock, rxblock; - int txcomplete, rxcomplete; - - struct grcan_filter sfilter; - struct grcan_filter afilter; - int config_changed; /* 0=no changes, 1=changes ==> a Core reset is needed */ - struct grcan_config config; - struct grcan_stats stats; - - rtems_id rx_sem, tx_sem, txempty_sem, dev_sem; - SPIN_DECLARE(devlock); -}; - static void __inline__ grcan_hw_reset(struct grcan_regs *regs); -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int max); - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int count); - static void grcan_hw_config( - struct grcan_regs *regs, + struct grcan_priv *pDev, struct grcan_config *conf); static void grcan_hw_accept( @@ -164,21 +94,40 @@ static void grcan_hw_sync( static void grcan_interrupt(void *arg); -#ifdef GRCAN_REG_BYPASS_CACHE -#define READ_REG(address) grlib_read_uncached32((unsigned int)(address)) -#else -#define READ_REG(address) (*(volatile unsigned int *)(address)) -#endif +#define NELEM(a) ((int) (sizeof (a) / sizeof (a[0]))) -#ifdef GRCAN_DMA_BYPASS_CACHE -#define READ_DMA_WORD(address) grlib_read_uncached32((unsigned int)(address)) -#define READ_DMA_BYTE(address) grlib_read_uncached8((unsigned int)(address)) -#else -#define READ_DMA_WORD(address) (*(volatile unsigned int *)(address)) -#define READ_DMA_BYTE(address) (*(volatile unsigned char *)(address)) -#endif +/* GRCAN nominal boundaries for baud-rate paramters */ +struct grlib_canbtrs_ranges grcan_btrs_ranges = { + .max_scaler = 256*8, /* scaler is multiplied by BPR in steps 1,2,4,8 */ + .has_bpr = 1, + .divfactor = 2, + .min_tseg1 = 1, + .max_tseg1 = 15, + .min_tseg2 = 2, + .max_tseg2 = 8, +}; -#define NELEM(a) ((int) (sizeof (a) / sizeof (a[0]))) +/* GRCANFD nominal boundaries */ +struct grlib_canbtrs_ranges grcanfd_nom_btrs_ranges = { + .max_scaler = 256, + .has_bpr = 0, + .divfactor = 1, + .min_tseg1 = 2, + .max_tseg1 = 63, + .min_tseg2 = 2, + .max_tseg2 = 16, +}; + +/* GRCANFD flexible baud-rate boundaries */ +struct grlib_canbtrs_ranges grcanfd_fd_btrs_ranges = { + .max_scaler = 256, + .has_bpr = 0, + .divfactor = 1, + .min_tseg1 = 1, + .max_tseg1 = 15, + .min_tseg2 = 2, + .max_tseg2 = 8, +}; static int grcan_count = 0; static struct grcan_priv *priv_tab[GRCAN_COUNT_MAX]; @@ -202,6 +151,7 @@ struct amba_dev_id grcan_ids[] = { {VENDOR_GAISLER, GAISLER_GRCAN}, {VENDOR_GAISLER, GAISLER_GRHCAN}, + {VENDOR_GAISLER, GAISLER_GRCANFD}, {0, 0} /* Mark end of table */ }; @@ -294,6 +244,8 @@ int grcan_device_init(struct grcan_priv *pDev) pDev->irq = pnpinfo->irq; pDev->regs = (struct grcan_regs *)pnpinfo->apb_slv->start; pDev->minor = pDev->dev->minor_drv; + if (ambadev->id.device == GAISLER_GRCANFD) + pDev->fd_capable = 1; /* Get frequency in Hz */ if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->corefreq_hz) ) { @@ -373,7 +325,7 @@ static rtems_device_driver grcan_hw_start(struct grcan_priv *pDev) * and Setup timing */ if (pDev->config_changed) { - grcan_hw_config(pDev->regs, &pDev->config); + grcan_hw_config(pDev, &pDev->config); pDev->config_changed = 0; } @@ -456,9 +408,10 @@ static void grcan_sw_stop(struct grcan_priv *pDev) rtems_semaphore_release(pDev->txempty_sem); } -static void grcan_hw_config(struct grcan_regs *regs, struct grcan_config *conf) +static void grcan_hw_config(struct grcan_priv *pDev, struct grcan_config *conf) { unsigned int config = 0; + struct grcan_regs *regs = pDev->regs; /* Reset HurriCANe Core */ regs->ctrl = 0; @@ -479,13 +432,29 @@ static void grcan_hw_config(struct grcan_regs *regs, struct grcan_config *conf) config |= GRCAN_CFG_ENABLE1; /* Timing */ - config |= (conf->timing.bpr << GRCAN_CFG_BPR_BIT) & GRCAN_CFG_BPR; - config |= (conf->timing.rsj << GRCAN_CFG_RSJ_BIT) & GRCAN_CFG_RSJ; - config |= (conf->timing.ps1 << GRCAN_CFG_PS1_BIT) & GRCAN_CFG_PS1; - config |= (conf->timing.ps2 << GRCAN_CFG_PS2_BIT) & GRCAN_CFG_PS2; - config |= - (conf->timing.scaler << GRCAN_CFG_SCALER_BIT) & GRCAN_CFG_SCALER; - + if (!pDev->fd_capable) { + config |= (conf->timing.bpr << GRCAN_CFG_BPR_BIT) & + GRCAN_CFG_BPR; + config |= (conf->timing.rsj << GRCAN_CFG_RSJ_BIT) & + GRCAN_CFG_RSJ; + config |= (conf->timing.ps1 << GRCAN_CFG_PS1_BIT) & + GRCAN_CFG_PS1; + config |= (conf->timing.ps2 << GRCAN_CFG_PS2_BIT) & + GRCAN_CFG_PS2; + config |= (conf->timing.scaler << GRCAN_CFG_SCALER_BIT) & + GRCAN_CFG_SCALER; + } else { + regs->nbtr = + (conf->timing.scaler << GRCANFD_NBTR_SCALER_BIT) | + (conf->timing.ps1 << GRCANFD_NBTR_PS1_BIT) | + (conf->timing.ps2 << GRCANFD_NBTR_PS2_BIT) | + (conf->timing.rsj << GRCANFD_NBTR_SJW_BIT); + regs->fdbtr = + (conf->timing_fd.scaler << GRCANFD_FDBTR_SCALER_BIT) | + (conf->timing_fd.ps1 << GRCANFD_FDBTR_PS1_BIT) | + (conf->timing_fd.ps2 << GRCANFD_FDBTR_PS2_BIT) | + (conf->timing_fd.sjw << GRCANFD_FDBTR_SJW_BIT); + } /* Write configuration */ regs->conf = config; @@ -520,338 +489,7 @@ static void grcan_hw_sync(struct grcan_regs *regs, struct grcan_filter *sfilter) regs->smask = sfilter->mask; } -static unsigned int grcan_hw_rxavail( - unsigned int rp, - unsigned int wp, unsigned int size -) -{ - if (rp == wp) { - /* read pointer and write pointer is equal only - * when RX buffer is empty. - */ - return 0; - } - - if (wp > rp) { - return (wp - rp) / GRCAN_MSG_SIZE; - } else { - return (size - (rp - wp)) / GRCAN_MSG_SIZE; - } -} - -static unsigned int grcan_hw_txspace( - unsigned int rp, - unsigned int wp, - unsigned int size -) -{ - unsigned int left; - - if (rp == wp) { - /* read pointer and write pointer is equal only - * when TX buffer is empty. - */ - return size / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS; - } - - /* size - 4 - abs(read-write) */ - if (wp > rp) { - left = size - (wp - rp); - } else { - left = rp - wp; - } - - return left / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS; -} - -#define MIN_TSEG1 1 -#define MIN_TSEG2 2 -#define MAX_TSEG1 14 -#define MAX_TSEG2 8 - -static int grcan_calc_timing( - unsigned int baud, /* The requested BAUD to calculate timing for */ - unsigned int core_hz, /* Frequency in Hz of GRCAN Core */ - unsigned int sampl_pt, - struct grcan_timing *timing /* result is placed here */ -) -{ - int best_error = 1000000000; - int error; - int best_tseg = 0, best_brp = 0, brp = 0; - int tseg = 0, tseg1 = 0, tseg2 = 0; - int sjw = 1; - - /* Default to 90% */ - if ((sampl_pt < 50) || (sampl_pt > 99)) { - sampl_pt = GRCAN_SAMPLING_POINT; - } - - if ((baud < 5000) || (baud > 1000000)) { - /* invalid speed mode */ - return -1; - } - - /* find best match, return -2 if no good reg - * combination is available for this frequency - */ - - /* some heuristic specials */ - if (baud > ((1000000 + 500000) / 2)) - sampl_pt = 75; - - if (baud < ((12500 + 10000) / 2)) - sampl_pt = 75; - - /* tseg even = round down, odd = round up */ - for ( - tseg = (MIN_TSEG1 + MIN_TSEG2 + 2) * 2; - tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1; - tseg++ - ) { - brp = core_hz / ((1 + tseg / 2) * baud) + tseg % 2; - if ( - (brp <= 0) || - ((brp > 256 * 1) && (brp <= 256 * 2) && (brp & 0x1)) || - ((brp > 256 * 2) && (brp <= 256 * 4) && (brp & 0x3)) || - ((brp > 256 * 4) && (brp <= 256 * 8) && (brp & 0x7)) || - (brp > 256 * 8) - ) - continue; - - error = baud - core_hz / (brp * (1 + tseg / 2)); - if (error < 0) { - error = -error; - } - - if (error <= best_error) { - best_error = error; - best_tseg = tseg / 2; - best_brp = brp - 1; - } - } - - if (best_error && (baud / best_error < 10)) { - return -2; - } else if (!timing) - return 0; /* nothing to store result in, but a valid bitrate can be calculated */ - - tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100; - - if (tseg2 < MIN_TSEG2) { - tseg2 = MIN_TSEG2; - } - - if (tseg2 > MAX_TSEG2) { - tseg2 = MAX_TSEG2; - } - - tseg1 = best_tseg - tseg2 - 2; - - if (tseg1 > MAX_TSEG1) { - tseg1 = MAX_TSEG1; - tseg2 = best_tseg - tseg1 - 2; - } - - /* Get scaler and BRP from pseudo BRP */ - if (best_brp <= 256) { - timing->scaler = best_brp; - timing->bpr = 0; - } else if (best_brp <= 256 * 2) { - timing->scaler = ((best_brp + 1) >> 1) - 1; - timing->bpr = 1; - } else if (best_brp <= 256 * 4) { - timing->scaler = ((best_brp + 1) >> 2) - 1; - timing->bpr = 2; - } else { - timing->scaler = ((best_brp + 1) >> 3) - 1; - timing->bpr = 3; - } - - timing->ps1 = tseg1 + 1; - timing->ps2 = tseg2; - timing->rsj = sjw; - - return 0; -} - -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int max -) -{ - int i, j; - CANMsg *dest; - struct grcan_msg *source, tmp; - unsigned int wp, rp, size, rxmax, addr; - int trunk_msg_cnt; - - FUNCDBG(); - - wp = READ_REG(®s->rx0wr); - rp = READ_REG(®s->rx0rd); - - /* - * Due to hardware wrap around simplification write pointer will - * never reach the read pointer, at least a gap of 8 bytes. - * The only time they are equal is when the read pointer has - * reached the write pointer (empty buffer) - * - */ - if (wp != rp) { - /* Not empty, we have received chars... - * Read as much as possible from DMA buffer - */ - size = READ_REG(®s->rx0size); - - /* Get number of bytes available in RX buffer */ - trunk_msg_cnt = grcan_hw_rxavail(rp, wp, size); - - /* truncate size if user space buffer hasn't room for - * all received chars. - */ - if (trunk_msg_cnt > max) - trunk_msg_cnt = max; - - /* Read until i is 0 */ - i = trunk_msg_cnt; - - addr = (unsigned int)pDev->rx; - source = (struct grcan_msg *)(addr + rp); - dest = buffer; - rxmax = addr + (size - GRCAN_MSG_SIZE); - - /* Read as many can messages as possible */ - while (i > 0) { - /* Read CAN message from DMA buffer */ - tmp.head[0] = READ_DMA_WORD(&source->head[0]); - tmp.head[1] = READ_DMA_WORD(&source->head[1]); - if (tmp.head[1] & 0x4) { - DBGC(DBG_RX, "overrun\n"); - } - if (tmp.head[1] & 0x2) { - DBGC(DBG_RX, "bus-off mode\n"); - } - if (tmp.head[1] & 0x1) { - DBGC(DBG_RX, "error-passive mode\n"); - } - /* Convert one grcan CAN message to one "software" CAN message */ - dest->extended = tmp.head[0] >> 31; - dest->rtr = (tmp.head[0] >> 30) & 0x1; - if (dest->extended) { - dest->id = tmp.head[0] & 0x3fffffff; - } else { - dest->id = (tmp.head[0] >> 18) & 0xfff; - } - dest->len = tmp.head[1] >> 28; - for (j = 0; j < dest->len; j++) - dest->data[j] = READ_DMA_BYTE(&source->data[j]); - - /* wrap around if neccessary */ - source = - ((unsigned int)source >= rxmax) ? - (struct grcan_msg *)addr : source + 1; - dest++; /* straight user buffer */ - i--; - } - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->rx0rd = (unsigned int) source - addr; - regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - trunk_msg_cnt = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return trunk_msg_cnt; - } - return 0; -} - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int count -) -{ - unsigned int rp, wp, size, txmax, addr; - int ret; - struct grcan_msg *dest; - CANMsg *source; - int space_left; - unsigned int tmp; - int i; - - DBGC(DBG_TX, "\n"); - /*FUNCDBG(); */ - - rp = READ_REG(®s->tx0rd); - wp = READ_REG(®s->tx0wr); - size = READ_REG(®s->tx0size); - - space_left = grcan_hw_txspace(rp, wp, size); - - /* is circular fifo full? */ - if (space_left < 1) - return 0; - - /* Truncate size */ - if (space_left > count) - space_left = count; - ret = space_left; - - addr = (unsigned int)pDev->tx; - - dest = (struct grcan_msg *)(addr + wp); - source = (CANMsg *) buffer; - txmax = addr + (size - GRCAN_MSG_SIZE); - - while (space_left > 0) { - /* Convert and write CAN message to DMA buffer */ - if (source->extended) { - tmp = (1 << 31) | (source->id & 0x3fffffff); - } else { - tmp = (source->id & 0xfff) << 18; - } - if (source->rtr) - tmp |= (1 << 30); - dest->head[0] = tmp; - dest->head[1] = source->len << 28; - for (i = 0; i < source->len; i++) - dest->data[i] = source->data[i]; - source++; /* straight user buffer */ - dest = - ((unsigned int)dest >= txmax) ? - (struct grcan_msg *)addr : dest + 1; - space_left--; - } - - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->tx0wr = (unsigned int) dest - addr; - regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - ret = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return ret; -} - -static int grcan_wait_rxdata(struct grcan_priv *pDev, int min) +int grcan_wait_rxdata(struct grcan_priv *pDev, int min) { unsigned int wp, rp, size, irq; unsigned int irq_trunk, dataavail; @@ -934,7 +572,7 @@ static int grcan_wait_rxdata(struct grcan_priv *pDev, int min) * min must be at least WRAP_AROUND_TX_MSGS less than max buffer capacity * (pDev->txbuf_size/GRCAN_MSG_SIZE) for this algo to work. */ -static int grcan_wait_txspace(struct grcan_priv *pDev, int min) +int grcan_wait_txspace(struct grcan_priv *pDev, int min) { int wait, state; unsigned int irq, rp, wp, size, space_left; @@ -1007,7 +645,7 @@ static int grcan_wait_txspace(struct grcan_priv *pDev, int min) return state2err[pDev->started]; } - /* At this point the TxIRQ has been masked, we ned not to mask it */ + /* At this point the TxIRQ has been masked, we need not to mask it */ return 0; } @@ -1211,6 +849,7 @@ void *grcan_open(int dev_no) struct grcan_priv *pDev; void *ret; union drvmgr_key_value *value; + struct grlib_canbtrs_ranges *br; FUNCDBG(); @@ -1282,7 +921,13 @@ void *grcan_open(int dev_no) pDev->sfilter.code = 0x00000000; /* Calculate default timing register values */ - grcan_calc_timing(GRCAN_DEFAULT_BAUD,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&pDev->config.timing); + if (pDev->fd_capable) + br = &grcanfd_nom_btrs_ranges; + else + br = &grcan_btrs_ranges; + grlib_canbtrs_calc_timing( + GRCAN_DEFAULT_BAUD, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, + br, (struct grlib_canbtrs_timing *)&pDev->config.timing); if ( grcan_alloc_buffers(pDev,1,1) ) { ret = NULL; @@ -1316,174 +961,11 @@ int grcan_close(void *d) return 0; } -int grcan_read(void *d, CANMsg *msg, size_t ucount) -{ - struct grcan_priv *pDev = d; - CANMsg *dest; - unsigned int count, left; - int nread; - int req_cnt; - - FUNCDBG(); - - dest = msg; - req_cnt = ucount; - - if ( (!dest) || (req_cnt<1) ) - return GRCAN_RET_INVARG; - - if (pDev->started != STATE_STARTED) { - return GRCAN_RET_NOTSTARTED; - } - - DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount); - - nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt); - if (nread < 0) { - return nread; - } - count = nread; - if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){ - if ( count > 0 ) { - /* Successfully received messages (at least one) */ - return count; - } - - /* nothing read, shall we block? */ - if ( !pDev->rxblock ) { - /* non-blocking mode */ - return GRCAN_RET_TIMEOUT; - } - } - - while (count == 0 || (pDev->rxcomplete && (count!=req_cnt))) { - if (!pDev->rxcomplete) { - left = 1; /* return as soon as there is one message available */ - } else { - left = req_cnt - count; /* return as soon as all data are available */ - - /* never wait for more than the half the maximum size of the receive buffer - * Why? We need some time to copy buffer before to catch up with hw, - * otherwise we would have to copy everything when the data has been - * received. - */ - if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){ - left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2; - } - } - - nread = grcan_wait_rxdata(pDev, left); - if (nread) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread or a bus-off. Return error code. - */ - return nread; - } - - /* Try read bytes from circular buffer */ - nread = grcan_hw_read_try( - pDev, - pDev->regs, - dest+count, - req_cnt-count); - - if (nread < 0) { - /* The read was aborted by bus-off. */ - return nread; - } - count += nread; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - return count; -} - -int grcan_write(void *d, CANMsg *msg, size_t ucount) +int grcan_canfd_capable(void *d) { struct grcan_priv *pDev = d; - CANMsg *source; - unsigned int count, left; - int nwritten; - int req_cnt; - - DBGC(DBG_TX,"\n"); - - if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing) - return GRCAN_RET_NOTSTARTED; - - req_cnt = ucount; - source = (CANMsg *) msg; - - /* check proper length and buffer pointer */ - if (( req_cnt < 1) || (source == NULL) ){ - return GRCAN_RET_INVARG; - } - - nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt); - if (nwritten < 0) { - return nwritten; - } - count = nwritten; - if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) { - if ( count > 0 ) { - /* Successfully transmitted chars (at least one char) */ - return count; - } - - /* nothing written, shall we block? */ - if ( !pDev->txblock ) { - /* non-blocking mode */ - return GRCAN_RET_TIMEOUT; - } - } - /* if in txcomplete mode we need to transmit all chars */ - while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){ - /*** block until room to fit all or as much of transmit buffer as possible - * IRQ comes. Set up a valid IRQ point so that an IRQ is received - * when we can put a chunk of data into transmit fifo - */ - if ( !pDev->txcomplete ){ - left = 1; /* wait for anything to fit buffer */ - }else{ - left = req_cnt - count; /* wait for all data to fit in buffer */ - - /* never wait for more than the half the maximum size of the transmit - * buffer - * Why? We need some time to fill buffer before hw catches up. - */ - if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){ - left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2; - } - } - - nwritten = grcan_wait_txspace(pDev,left); - /* Wait until more room in transmit buffer */ - if ( nwritten ) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread. To avoid deadlock we return directly - * with error status. - */ - return nwritten; - } - - /* Try read bytes from circular buffer */ - nwritten = grcan_hw_write_try( - pDev, - pDev->regs, - source+count, - req_cnt-count); - - if (nwritten < 0) { - /* Write was aborted by bus-off. */ - return nwritten; - } - count += nwritten; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - - return count; + return pDev->fd_capable; } int grcan_start(void *d) @@ -1712,51 +1194,6 @@ int grcan_clr_stats(void *d) return 0; } -int grcan_set_speed(void *d, unsigned int speed) -{ - struct grcan_priv *pDev = d; - struct grcan_timing timing; - int ret; - - FUNCDBG(); - - /* cannot change speed during run mode */ - if (pDev->started == STATE_STARTED) - return -1; - - /* get speed rate from argument */ - ret = grcan_calc_timing(speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, &timing); - if ( ret ) - return -2; - - /* save timing/speed */ - pDev->config.timing = timing; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_btrs(void *d, const struct grcan_timing *timing) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - /* Set BTR registers manually - * Read GRCAN/HurriCANe Manual. - */ - if (pDev->started == STATE_STARTED) - return -1; - - if ( !timing ) - return -2; - - pDev->config.timing = *timing; - pDev->config_changed = 1; - - return 0; -} - int grcan_set_afilter(void *d, const struct grcan_filter *filter) { struct grcan_priv *pDev = d; |