source: rtems/bsps/sparc/shared/can/grcan.c @ 31720925

5
Last change on this file since 31720925 was 31720925, checked in by Sebastian Huber <sebastian.huber@…>, on 12/22/18 at 06:13:44

grlib: Move header files

Update #3678.

  • Property mode set to 100644
File size: 45.1 KB
RevLine 
[226455f]1/*
[44b06ca]2 *  GRCAN driver
[3681925]3 *
[226455f]4 *  COPYRIGHT (c) 2007.
[3681925]5 *  Cobham Gaisler AB.
[226455f]6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
[c499856]9 *  http://www.rtems.org/license/LICENSE.
[226455f]10 */
11
12#include <bsp.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <assert.h>
17#include <ctype.h>
18#include <rtems/bspIo.h>
19
[31720925]20#include <grlib/grcan.h>
[3681925]21#include <drvmgr/drvmgr.h>
[31720925]22#include <grlib/ambapp_bus.h>
23#include <grlib/ambapp.h>
[226455f]24
[31720925]25#include <grlib/grlib_impl.h>
[7b8a920]26
[ad203e58]27/* Maximum number of GRCAN devices supported by driver */
28#define GRCAN_COUNT_MAX 8
29
[226455f]30#define WRAP_AROUND_TX_MSGS 1
31#define WRAP_AROUND_RX_MSGS 2
32#define GRCAN_MSG_SIZE sizeof(struct grcan_msg)
33#define BLOCK_SIZE (16*4)
34
[3681925]35/* grcan needs to have it buffers aligned to 1k boundaries */
36#define BUFFER_ALIGNMENT_NEEDS 1024
37
[226455f]38/* Default Maximium buffer size for statically allocated buffers */
39#ifndef TX_BUF_SIZE
[3681925]40 #define TX_BUF_SIZE (BLOCK_SIZE*16)
[226455f]41#endif
42
43/* Make receiver buffers bigger than transmitt */
44#ifndef RX_BUF_SIZE
[3681925]45 #define RX_BUF_SIZE ((3*BLOCK_SIZE)*16)
[226455f]46#endif
47
48#ifndef IRQ_CLEAR_PENDING
[44b06ca]49 #define IRQ_CLEAR_PENDING(irqno)
[226455f]50#endif
51
52#ifndef IRQ_UNMASK
[44b06ca]53 #define IRQ_UNMASK(irqno)
[226455f]54#endif
55
56#ifndef IRQ_MASK
[44b06ca]57 #define IRQ_MASK(irqno)
[226455f]58#endif
59
60#ifndef GRCAN_DEFAULT_BAUD
[3681925]61 /* default to 500kbits/s */
62 #define GRCAN_DEFAULT_BAUD 500000
[226455f]63#endif
64
[e3481dcd]65#ifndef GRCAN_SAMPLING_POINT
[3681925]66 #define GRCAN_SAMPLING_POINT 80
[e3481dcd]67#endif
68
[226455f]69/* Uncomment for debug output */
70/****************** DEBUG Definitions ********************/
71#define DBG_TX 2
72#define DBG_RX 4
[2d3d8f96]73#define DBG_STATE 8
[226455f]74
[2d3d8f96]75#define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX )
[e3481dcd]76/*
77#define DEBUG
78#define DEBUGFUNCS
79*/
[31720925]80#include <grlib/debug_defs.h>
[226455f]81
82/*********************************************************/
83
[2d3d8f96]84int state2err[4] = {
85        /* STATE_STOPPED */ GRCAN_RET_NOTSTARTED,
86        /* STATE_STARTED */ GRCAN_RET_OK,
87        /* STATE_BUSOFF  */ GRCAN_RET_BUSOFF,
88        /* STATE_AHBERR  */ GRCAN_RET_AHBERR
89};
90
[226455f]91struct grcan_msg {
[3681925]92        unsigned int head[2];
93        unsigned char data[8];
[226455f]94};
95
96struct grcan_config {
97        struct grcan_timing timing;
98        struct grcan_selection selection;
99        int abort;
100        int silent;
101};
102
103struct grcan_priv {
[3681925]104        struct drvmgr_dev *dev; /* Driver manager device */
105        char devName[32];       /* Device Name */
106        unsigned int baseaddr, ram_base;
107        struct grcan_regs *regs;
108        int irq;
109        int minor;
110        int open;
111        int started;
112        unsigned int channel;
113        int flushing;
114        unsigned int corefreq_hz;
115
116        /* Circular DMA buffers */
117        void *_rx, *_rx_hw;
118        void *_tx, *_tx_hw;
119        void *txbuf_adr;
120        void *rxbuf_adr;
121        struct grcan_msg *rx;
122        struct grcan_msg *tx;
123        unsigned int rxbuf_size;    /* requested RX buf size in bytes */
124        unsigned int txbuf_size;    /* requested TX buf size in bytes */
125
126        int txblock, rxblock;
127        int txcomplete, rxcomplete;
128
129        struct grcan_filter sfilter;
130        struct grcan_filter afilter;
131        int config_changed; /* 0=no changes, 1=changes ==> a Core reset is needed */
132        struct grcan_config config;
133        struct grcan_stats stats;
134
135        rtems_id rx_sem, tx_sem, txempty_sem, dev_sem;
[7b8a920]136        SPIN_DECLARE(devlock);
[226455f]137};
138
[3681925]139static void __inline__ grcan_hw_reset(struct grcan_regs *regs);
140
[2d3d8f96]141static int grcan_hw_read_try(
[bc40b4d]142        struct grcan_priv *pDev,
143        struct grcan_regs *regs,
144        CANMsg *buffer,
145        int max);
[226455f]146
[2d3d8f96]147static int grcan_hw_write_try(
[bc40b4d]148        struct grcan_priv *pDev,
149        struct grcan_regs *regs,
150        CANMsg *buffer,
151        int count);
[226455f]152
153static void grcan_hw_config(
[bc40b4d]154        struct grcan_regs *regs,
155        struct grcan_config *conf);
[44b06ca]156
[226455f]157static void grcan_hw_accept(
[bc40b4d]158        struct grcan_regs *regs,
159        struct grcan_filter *afilter);
[226455f]160
161static void grcan_hw_sync(
[bc40b4d]162        struct grcan_regs *regs,
163        struct grcan_filter *sfilter);
[226455f]164
[3681925]165static void grcan_interrupt(void *arg);
[226455f]166
167#ifdef GRCAN_REG_BYPASS_CACHE
168#define READ_REG(address) _grcan_read_nocache((unsigned int)(address))
169#else
[e3481dcd]170#define READ_REG(address) (*(volatile unsigned int *)(address))
[226455f]171#endif
172
173#ifdef GRCAN_DMA_BYPASS_CACHE
174#define READ_DMA_WORD(address) _grcan_read_nocache((unsigned int)(address))
175#define READ_DMA_BYTE(address) _grcan_read_nocache_byte((unsigned int)(address))
176static unsigned char __inline__ _grcan_read_nocache_byte(unsigned int address)
177{
[3681925]178        unsigned char tmp;
179        __asm__ (" lduba [%1]1, %0 "
180            : "=r"(tmp)
181            : "r"(address)
182        );
183        return tmp;
[226455f]184}
185#else
[e3481dcd]186#define READ_DMA_WORD(address) (*(volatile unsigned int *)(address))
187#define READ_DMA_BYTE(address) (*(volatile unsigned char *)(address))
[226455f]188#endif
189
190#if defined(GRCAN_REG_BYPASS_CACHE) || defined(GRCAN_DMA_BYPASS_CACHE)
191static unsigned int __inline__ _grcan_read_nocache(unsigned int address)
192{
[3681925]193        unsigned int tmp;
194        __asm__ (" lda [%1]1, %0 "
195                : "=r"(tmp)
196                : "r"(address)
197        );
198        return tmp;
[226455f]199}
200#endif
201
[ca4c4164]202#define NELEM(a) ((int) (sizeof (a) / sizeof (a[0])))
203
[ad203e58]204static int grcan_count = 0;
205static struct grcan_priv *priv_tab[GRCAN_COUNT_MAX];
[3681925]206
207/******************* Driver manager interface ***********************/
208
209/* Driver prototypes */
210int grcan_device_init(struct grcan_priv *pDev);
211
212int grcan_init2(struct drvmgr_dev *dev);
213int grcan_init3(struct drvmgr_dev *dev);
214
215struct drvmgr_drv_ops grcan_ops =
216{
217        .init = {NULL, grcan_init2, grcan_init3, NULL},
218        .remove = NULL,
219        .info = NULL
220};
221
222struct amba_dev_id grcan_ids[] =
223{
224        {VENDOR_GAISLER, GAISLER_GRCAN},
225        {VENDOR_GAISLER, GAISLER_GRHCAN},
226        {0, 0}          /* Mark end of table */
227};
228
229struct amba_drv_info grcan_drv_info =
230{
231        {
232                DRVMGR_OBJ_DRV,                 /* Driver */
233                NULL,                           /* Next driver */
234                NULL,                           /* Device list */
235                DRIVER_AMBAPP_GAISLER_GRCAN_ID, /* Driver ID */
236                "GRCAN_DRV",                    /* Driver Name */
237                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
238                &grcan_ops,
239                NULL,                           /* Funcs */
240                0,                              /* No devices yet */
241                0,
242        },
243        &grcan_ids[0]
244};
245
246void grcan_register_drv (void)
247{
248        DBG("Registering GRCAN driver\n");
249        drvmgr_drv_register(&grcan_drv_info.general);
250}
251
252int grcan_init2(struct drvmgr_dev *dev)
253{
254        struct grcan_priv *priv;
255
256        DBG("GRCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
[ad203e58]257        if (GRCAN_COUNT_MAX <= grcan_count)
258                return DRVMGR_ENORES;
[11f3b9a]259        priv = dev->priv = grlib_calloc(1, sizeof(*priv));
[3681925]260        if ( !priv )
261                return DRVMGR_NOMEM;
262        priv->dev = dev;
263
264        /* This core will not find other cores, so we wait for init2() */
265
266        return DRVMGR_OK;
267}
268
269int grcan_init3(struct drvmgr_dev *dev)
270{
271        struct grcan_priv *priv;
272        char prefix[32];
273
274        priv = dev->priv;
275
[ad203e58]276        /*
[3681925]277         * Now we take care of device initialization.
278         */
279
280        if ( grcan_device_init(priv) ) {
281                return DRVMGR_FAIL;
282        }
283
[ad203e58]284        priv_tab[grcan_count] = priv;
285        grcan_count++;
286
[3681925]287        /* Get Filesystem name prefix */
288        prefix[0] = '\0';
289        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
290                /* Failed to get prefix, make sure of a unique FS name
291                 * by using the driver minor.
292                 */
[ca4c4164]293                sprintf(priv->devName, "grcan%d", dev->minor_drv);
[3681925]294        } else {
295                /* Got special prefix, this means we have a bus prefix
296                 * And we should use our "bus minor"
297                 */
[ca4c4164]298                sprintf(priv->devName, "%sgrcan%d", prefix, dev->minor_bus);
[3681925]299        }
300
301        return DRVMGR_OK;
302}
303
304int grcan_device_init(struct grcan_priv *pDev)
305{
306        struct amba_dev_info *ambadev;
307        struct ambapp_core *pnpinfo;
308
309        /* Get device information from AMBA PnP information */
310        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
311        if ( ambadev == NULL ) {
312                return -1;
313        }
314        pnpinfo = &ambadev->info;
315        pDev->irq = pnpinfo->irq;
316        pDev->regs = (struct grcan_regs *)pnpinfo->apb_slv->start;
317        pDev->minor = pDev->dev->minor_drv;
318
319        /* Get frequency in Hz */
320        if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->corefreq_hz) ) {
321                return -1;
322        }
323
324        DBG("GRCAN frequency: %d Hz\n", pDev->corefreq_hz);
325
326        /* Reset Hardware before attaching IRQ handler */
327        grcan_hw_reset(pDev->regs);
328
329        /* RX Semaphore created with count = 0 */
330        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'R', '0' + pDev->minor),
331                0,
332                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
333                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
334                0,
335                &pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
336                return RTEMS_INTERNAL_ERROR;
337        }
338
339        /* TX Semaphore created with count = 0 */
340        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'T', '0' + pDev->minor),
341                0,
342                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
343                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
344                0,
345                &pDev->tx_sem) != RTEMS_SUCCESSFUL ) {
346                return RTEMS_INTERNAL_ERROR;
347        }
348
349        /* TX Empty Semaphore created with count = 0 */
350        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'E', '0' + pDev->minor),
351                0,
352                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
353                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
354                0,
355                &pDev->txempty_sem) != RTEMS_SUCCESSFUL ) {
356                return RTEMS_INTERNAL_ERROR;
357        }
358
359        /* Device Semaphore created with count = 1 */
360        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'A', '0' + pDev->minor),
361                1,
362                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
363                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
364                0,
365                &pDev->dev_sem) != RTEMS_SUCCESSFUL ) {
366                return RTEMS_INTERNAL_ERROR;
367        }
368
369        return 0;
370}
[226455f]371
372static void __inline__ grcan_hw_reset(struct grcan_regs *regs)
373{
374        regs->ctrl = GRCAN_CTRL_RESET;
375}
376
[ad203e58]377static rtems_device_driver grcan_hw_start(struct grcan_priv *pDev)
[226455f]378{
[bc40b4d]379        /*
380         * tmp is set but never used. GCC gives a warning for this
381         * and we need to tell GCC not to complain.
382         */
383        unsigned int tmp RTEMS_UNUSED;
[f07b0e65]384
[7b8a920]385        SPIN_IRQFLAGS(oldLevel);
[44b06ca]386
[bc40b4d]387        FUNCDBG();
[44b06ca]388
[bc40b4d]389        /* Check that memory has been allocated successfully */
390        if (!pDev->tx || !pDev->rx)
391                return RTEMS_NO_MEMORY;
[44b06ca]392
[bc40b4d]393        /* Configure FIFO configuration register
394         * and Setup timing
395         */
396        if (pDev->config_changed) {
397                grcan_hw_config(pDev->regs, &pDev->config);
398                pDev->config_changed = 0;
399        }
[226455f]400
[bc40b4d]401        /* Setup receiver */
402        pDev->regs->rx0addr = (unsigned int)pDev->_rx_hw;
403        pDev->regs->rx0size = pDev->rxbuf_size;
[44b06ca]404
[bc40b4d]405        /* Setup Transmitter */
406        pDev->regs->tx0addr = (unsigned int)pDev->_tx_hw;
407        pDev->regs->tx0size = pDev->txbuf_size;
[44b06ca]408
[bc40b4d]409        /* Setup acceptance filters */
410        grcan_hw_accept(pDev->regs, &pDev->afilter);
[44b06ca]411
[bc40b4d]412        /* Sync filters */
413        grcan_hw_sync(pDev->regs, &pDev->sfilter);
[44b06ca]414
[bc40b4d]415        /* Clear status bits */
416        tmp = READ_REG(&pDev->regs->stat);
417        pDev->regs->stat = 0;
[44b06ca]418
[bc40b4d]419        /* Setup IRQ handling */
[44b06ca]420
[bc40b4d]421        /* Clear all IRQs */
422        tmp = READ_REG(&pDev->regs->pir);
423        pDev->regs->picr = 0x1ffff;
[44b06ca]424
[bc40b4d]425        /* unmask TxLoss|TxErrCntr|RxErrCntr|TxAHBErr|RxAHBErr|OR|OFF|PASS */
426        pDev->regs->imr = 0x1601f;
[44b06ca]427
[bc40b4d]428        /* Enable routing of the IRQs */
[7b8a920]429        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]430        IRQ_UNMASK(pDev->irq + GRCAN_IRQ_TXSYNC);
431        IRQ_UNMASK(pDev->irq + GRCAN_IRQ_RXSYNC);
432        IRQ_UNMASK(pDev->irq + GRCAN_IRQ_IRQ);
[7b8a920]433        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[44b06ca]434
[bc40b4d]435        /* Enable receiver/transmitter */
436        pDev->regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
437        pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
[44b06ca]438
[bc40b4d]439        /* Enable HurriCANe core */
440        pDev->regs->ctrl = GRCAN_CTRL_ENABLE;
[44b06ca]441
[bc40b4d]442        /* Leave transmitter disabled, it is enabled when
443         * trying to send something.
444         */
445        return RTEMS_SUCCESSFUL;
[226455f]446}
447
[ad203e58]448static void grcan_hw_stop(struct grcan_priv *pDev)
[226455f]449{
[bc40b4d]450        FUNCDBG();
451
452        /* Mask all IRQs */
453        pDev->regs->imr = 0;
454        IRQ_MASK(pDev->irq + GRCAN_IRQ_TXSYNC);
455        IRQ_MASK(pDev->irq + GRCAN_IRQ_RXSYNC);
456        IRQ_MASK(pDev->irq + GRCAN_IRQ_IRQ);
457
458        /* Disable receiver & transmitter */
459        pDev->regs->rx0ctrl = 0;
460        pDev->regs->tx0ctrl = 0;
[9855690]461}
[bc40b4d]462
[9855690]463static void grcan_sw_stop(struct grcan_priv *pDev)
464{
[91541551]465        /*
466         * Release semaphores to wake all threads waiting for an IRQ.
467         * The threads that
468         * get woken up must check started state in
[bc40b4d]469         * order to determine that they should return to
470         * user space with error status.
[91541551]471         *
472         * Entering into started mode again will reset the
473         * semaphore count.
[bc40b4d]474         */
[91541551]475        rtems_semaphore_release(pDev->rx_sem);
476        rtems_semaphore_release(pDev->tx_sem);
477        rtems_semaphore_release(pDev->txempty_sem);
[226455f]478}
479
[bc40b4d]480static void grcan_hw_config(struct grcan_regs *regs, struct grcan_config *conf)
[226455f]481{
[bc40b4d]482        unsigned int config = 0;
[44b06ca]483
[bc40b4d]484        /* Reset HurriCANe Core */
485        regs->ctrl = 0;
[44b06ca]486
[bc40b4d]487        if (conf->silent)
488                config |= GRCAN_CFG_SILENT;
[44b06ca]489
[bc40b4d]490        if (conf->abort)
491                config |= GRCAN_CFG_ABORT;
[44b06ca]492
[bc40b4d]493        if (conf->selection.selection)
494                config |= GRCAN_CFG_SELECTION;
[44b06ca]495
[bc40b4d]496        if (conf->selection.enable0)
497                config |= GRCAN_CFG_ENABLE0;
[44b06ca]498
[bc40b4d]499        if (conf->selection.enable1)
500                config |= GRCAN_CFG_ENABLE1;
[44b06ca]501
[bc40b4d]502        /* Timing */
503        config |= (conf->timing.bpr << GRCAN_CFG_BPR_BIT) & GRCAN_CFG_BPR;
504        config |= (conf->timing.rsj << GRCAN_CFG_RSJ_BIT) & GRCAN_CFG_RSJ;
505        config |= (conf->timing.ps1 << GRCAN_CFG_PS1_BIT) & GRCAN_CFG_PS1;
506        config |= (conf->timing.ps2 << GRCAN_CFG_PS2_BIT) & GRCAN_CFG_PS2;
507        config |=
508            (conf->timing.scaler << GRCAN_CFG_SCALER_BIT) & GRCAN_CFG_SCALER;
[44b06ca]509
[bc40b4d]510        /* Write configuration */
511        regs->conf = config;
[44b06ca]512
[bc40b4d]513        /* Enable HurriCANe Core */
514        regs->ctrl = GRCAN_CTRL_ENABLE;
[226455f]515}
516
517static void grcan_hw_accept(
[bc40b4d]518        struct grcan_regs *regs,
519        struct grcan_filter *afilter
520)
[226455f]521{
[bc40b4d]522        /* Disable Sync mask totaly (if we change scode or smask
523         * in an unfortunate way we may trigger a sync match)
524         */
525        regs->rx0mask = 0xffffffff;
526
527        /* Set Sync Filter in a controlled way */
528        regs->rx0code = afilter->code;
529        regs->rx0mask = afilter->mask;
[226455f]530}
531
[bc40b4d]532static void grcan_hw_sync(struct grcan_regs *regs, struct grcan_filter *sfilter)
[226455f]533{
[bc40b4d]534        /* Disable Sync mask totaly (if we change scode or smask
535         * in an unfortunate way we may trigger a sync match)
536         */
537        regs->smask = 0xffffffff;
538
539        /* Set Sync Filter in a controlled way */
540        regs->scode = sfilter->code;
541        regs->smask = sfilter->mask;
[226455f]542}
543
544static unsigned int grcan_hw_rxavail(
[bc40b4d]545        unsigned int rp,
546        unsigned int wp, unsigned int size
547)
[44b06ca]548{
[bc40b4d]549        if (rp == wp) {
550                /* read pointer and write pointer is equal only
551                 * when RX buffer is empty.
552                 */
553                return 0;
554        }
555
556        if (wp > rp) {
557                return (wp - rp) / GRCAN_MSG_SIZE;
558        } else {
559                return (size - (rp - wp)) / GRCAN_MSG_SIZE;
560        }
[226455f]561}
562
563static unsigned int grcan_hw_txspace(
[bc40b4d]564        unsigned int rp,
565        unsigned int wp,
566        unsigned int size
567)
[226455f]568{
[bc40b4d]569        unsigned int left;
570
571        if (rp == wp) {
572                /* read pointer and write pointer is equal only
573                 * when TX buffer is empty.
574                 */
575                return size / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS;
576        }
577
578        /* size - 4 - abs(read-write) */
579        if (wp > rp) {
580                left = size - (wp - rp);
581        } else {
582                left = rp - wp;
583        }
584
585        return left / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS;
[226455f]586}
587
[e3481dcd]588#define MIN_TSEG1 1
589#define MIN_TSEG2 2
590#define MAX_TSEG1 14
591#define MAX_TSEG2 8
592
[226455f]593static int grcan_calc_timing(
[bc40b4d]594        unsigned int baud,      /* The requested BAUD to calculate timing for */
595        unsigned int core_hz,   /* Frequency in Hz of GRCAN Core */
596        unsigned int sampl_pt,
597        struct grcan_timing *timing     /* result is placed here */
598)
[226455f]599{
[e3481dcd]600        int best_error = 1000000000;
601        int error;
[bc40b4d]602        int best_tseg = 0, best_brp = 0, brp = 0;
603        int tseg = 0, tseg1 = 0, tseg2 = 0;
[e3481dcd]604        int sjw = 1;
[44b06ca]605
[bc40b4d]606        /* Default to 90% */
607        if ((sampl_pt < 50) || (sampl_pt > 99)) {
608                sampl_pt = GRCAN_SAMPLING_POINT;
609        }
[e3481dcd]610
[bc40b4d]611        if ((baud < 5000) || (baud > 1000000)) {
[e3481dcd]612                /* invalid speed mode */
613                return -1;
614        }
[44b06ca]615
616        /* find best match, return -2 if no good reg
[e3481dcd]617         * combination is available for this frequency
[bc40b4d]618         */
[e3481dcd]619
620        /* some heuristic specials */
621        if (baud > ((1000000 + 500000) / 2))
622                sampl_pt = 75;
623
624        if (baud < ((12500 + 10000) / 2))
625                sampl_pt = 75;
626
627        /* tseg even = round down, odd = round up */
[bc40b4d]628        for (
629                tseg = (MIN_TSEG1 + MIN_TSEG2 + 2) * 2;
630                tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1;
631                tseg++
632        ) {
[e3481dcd]633                brp = core_hz / ((1 + tseg / 2) * baud) + tseg % 2;
[bc40b4d]634                if (
635                        (brp <= 0) ||
636                        ((brp > 256 * 1) && (brp <= 256 * 2) && (brp & 0x1)) ||
637                        ((brp > 256 * 2) && (brp <= 256 * 4) && (brp & 0x3)) ||
638                        ((brp > 256 * 4) && (brp <= 256 * 8) && (brp & 0x7)) ||
639                        (brp > 256 * 8)
640                )
[e3481dcd]641                        continue;
642
643                error = baud - core_hz / (brp * (1 + tseg / 2));
[bc40b4d]644                if (error < 0) {
[e3481dcd]645                        error = -error;
646                }
647
[bc40b4d]648                if (error <= best_error) {
[e3481dcd]649                        best_error = error;
[bc40b4d]650                        best_tseg = tseg / 2;
651                        best_brp = brp - 1;
[e3481dcd]652                }
653        }
654
[bc40b4d]655        if (best_error && (baud / best_error < 10)) {
[e3481dcd]656                return -2;
[bc40b4d]657        } else if (!timing)
658                return 0;       /* nothing to store result in, but a valid bitrate can be calculated */
[e3481dcd]659
660        tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100;
661
[bc40b4d]662        if (tseg2 < MIN_TSEG2) {
[e3481dcd]663                tseg2 = MIN_TSEG2;
664        }
665
[bc40b4d]666        if (tseg2 > MAX_TSEG2) {
[e3481dcd]667                tseg2 = MAX_TSEG2;
668        }
669
670        tseg1 = best_tseg - tseg2 - 2;
671
[bc40b4d]672        if (tseg1 > MAX_TSEG1) {
[e3481dcd]673                tseg1 = MAX_TSEG1;
674                tseg2 = best_tseg - tseg1 - 2;
675        }
[44b06ca]676
[bc40b4d]677        /* Get scaler and BRP from pseudo BRP */
678        if (best_brp <= 256) {
679                timing->scaler = best_brp;
680                timing->bpr = 0;
681        } else if (best_brp <= 256 * 2) {
682                timing->scaler = ((best_brp + 1) >> 1) - 1;
683                timing->bpr = 1;
684        } else if (best_brp <= 256 * 4) {
685                timing->scaler = ((best_brp + 1) >> 2) - 1;
686                timing->bpr = 2;
687        } else {
688                timing->scaler = ((best_brp + 1) >> 3) - 1;
689                timing->bpr = 3;
690        }
691
692        timing->ps1 = tseg1 + 1;
693        timing->ps2 = tseg2;
694        timing->rsj = sjw;
[e3481dcd]695
696        return 0;
[226455f]697}
698
[2d3d8f96]699static int grcan_hw_read_try(
[bc40b4d]700        struct grcan_priv *pDev,
701        struct grcan_regs *regs,
702        CANMsg * buffer,
703        int max
704)
[226455f]705{
[bc40b4d]706        int i, j;
707        CANMsg *dest;
708        struct grcan_msg *source, tmp;
[2d3d8f96]709        unsigned int wp, rp, size, rxmax, addr;
710        int trunk_msg_cnt;
[bc40b4d]711
712        FUNCDBG();
713
714        wp = READ_REG(&regs->rx0wr);
715        rp = READ_REG(&regs->rx0rd);
716
717        /*
718         * Due to hardware wrap around simplification write pointer will
719         * never reach the read pointer, at least a gap of 8 bytes.
720         * The only time they are equal is when the read pointer has
721         * reached the write pointer (empty buffer)
722         *
723         */
724        if (wp != rp) {
725                /* Not empty, we have received chars...
726                 * Read as much as possible from DMA buffer
727                 */
728                size = READ_REG(&regs->rx0size);
729
730                /* Get number of bytes available in RX buffer */
731                trunk_msg_cnt = grcan_hw_rxavail(rp, wp, size);
732
733                /* truncate size if user space buffer hasn't room for
734                 * all received chars.
735                 */
736                if (trunk_msg_cnt > max)
737                        trunk_msg_cnt = max;
738
739                /* Read until i is 0 */
740                i = trunk_msg_cnt;
741
742                addr = (unsigned int)pDev->rx;
743                source = (struct grcan_msg *)(addr + rp);
744                dest = buffer;
745                rxmax = addr + (size - GRCAN_MSG_SIZE);
746
747                /* Read as many can messages as possible */
748                while (i > 0) {
749                        /* Read CAN message from DMA buffer */
750                        tmp.head[0] = READ_DMA_WORD(&source->head[0]);
751                        tmp.head[1] = READ_DMA_WORD(&source->head[1]);
[2d3d8f96]752                        if (tmp.head[1] & 0x4) {
753                                DBGC(DBG_RX, "overrun\n");
754                        }
755                        if (tmp.head[1] & 0x2) {
756                                DBGC(DBG_RX, "bus-off mode\n");
757                        }
758                        if (tmp.head[1] & 0x1) {
759                                DBGC(DBG_RX, "error-passive mode\n");
760                        }
[bc40b4d]761                        /* Convert one grcan CAN message to one "software" CAN message */
762                        dest->extended = tmp.head[0] >> 31;
763                        dest->rtr = (tmp.head[0] >> 30) & 0x1;
764                        if (dest->extended) {
765                                dest->id = tmp.head[0] & 0x3fffffff;
766                        } else {
767                                dest->id = (tmp.head[0] >> 18) & 0xfff;
768                        }
769                        dest->len = tmp.head[1] >> 28;
770                        for (j = 0; j < dest->len; j++)
771                                dest->data[j] = READ_DMA_BYTE(&source->data[j]);
772
773                        /* wrap around if neccessary */
774                        source =
775                            ((unsigned int)source >= rxmax) ?
776                            (struct grcan_msg *)addr : source + 1;
777                        dest++; /* straight user buffer */
778                        i--;
779                }
[2d3d8f96]780                {
781                        /* A bus off interrupt may have occured after checking pDev->started */
782                        SPIN_IRQFLAGS(oldLevel);
783
784                        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
785                        if (pDev->started == STATE_STARTED) {
786                                regs->rx0rd = (unsigned int) source - addr;
787                                regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
788                        } else {
789                                DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
790                                trunk_msg_cnt = state2err[pDev->started];
791                        }
792                        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]793                }
794                return trunk_msg_cnt;
795        }
796        return 0;
[226455f]797}
798
[2d3d8f96]799static int grcan_hw_write_try(
[bc40b4d]800        struct grcan_priv *pDev,
801        struct grcan_regs *regs,
802        CANMsg * buffer,
803        int count
804)
[226455f]805{
[2d3d8f96]806        unsigned int rp, wp, size, txmax, addr;
807        int ret;
[bc40b4d]808        struct grcan_msg *dest;
809        CANMsg *source;
810        int space_left;
811        unsigned int tmp;
812        int i;
813
814        DBGC(DBG_TX, "\n");
815        /*FUNCDBG(); */
816
817        rp = READ_REG(&regs->tx0rd);
818        wp = READ_REG(&regs->tx0wr);
819        size = READ_REG(&regs->tx0size);
820
821        space_left = grcan_hw_txspace(rp, wp, size);
822
823        /* is circular fifo full? */
824        if (space_left < 1)
825                return 0;
826
827        /* Truncate size */
828        if (space_left > count)
829                space_left = count;
830        ret = space_left;
831
832        addr = (unsigned int)pDev->tx;
833
834        dest = (struct grcan_msg *)(addr + wp);
835        source = (CANMsg *) buffer;
836        txmax = addr + (size - GRCAN_MSG_SIZE);
837
838        while (space_left > 0) {
839                /* Convert and write CAN message to DMA buffer */
840                if (source->extended) {
841                        tmp = (1 << 31) | (source->id & 0x3fffffff);
842                } else {
843                        tmp = (source->id & 0xfff) << 18;
844                }
845                if (source->rtr)
846                        tmp |= (1 << 30);
847                dest->head[0] = tmp;
848                dest->head[1] = source->len << 28;
849                for (i = 0; i < source->len; i++)
850                        dest->data[i] = source->data[i];
851                source++;       /* straight user buffer */
852                dest =
853                    ((unsigned int)dest >= txmax) ?
854                    (struct grcan_msg *)addr : dest + 1;
855                space_left--;
856        }
857
[2d3d8f96]858        {
859                /* A bus off interrupt may have occured after checking pDev->started */
860                SPIN_IRQFLAGS(oldLevel);
861
862                SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
863                if (pDev->started == STATE_STARTED) {
864                        regs->tx0wr = (unsigned int) dest - addr;
865                        regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
866                } else {
867                        DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
868                        ret = state2err[pDev->started];
869                }
870                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]871        }
872        return ret;
[226455f]873}
874
[bc40b4d]875static int grcan_wait_rxdata(struct grcan_priv *pDev, int min)
[226455f]876{
[bc40b4d]877        unsigned int wp, rp, size, irq;
878        unsigned int irq_trunk, dataavail;
[2d3d8f96]879        int wait, state;
[7b8a920]880        SPIN_IRQFLAGS(oldLevel);
[bc40b4d]881
882        FUNCDBG();
883
884        /*** block until receive IRQ received
885         * Set up a valid IRQ point so that an IRQ is received
886         * when one or more messages are received
887         */
[7b8a920]888        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[2d3d8f96]889        state = pDev->started;
890
891        /* A bus off interrupt may have occured after checking pDev->started */
892        if (state != STATE_STARTED) {
893                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
894                if (state == STATE_BUSOFF) {
895                        DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
896                } else if (state == STATE_AHBERR) {
897                        DBGC(DBG_STATE, "cancelled due to a AHB error\n");
898                } else {
899                        DBGC(DBG_STATE, "cancelled due to STOP (unexpected) \n");
900                }
901                return state2err[state];
902        }
[bc40b4d]903
904        size = READ_REG(&pDev->regs->rx0size);
905        rp = READ_REG(&pDev->regs->rx0rd);
906        wp = READ_REG(&pDev->regs->rx0wr);
907
908        /**** Calculate IRQ Pointer ****/
909        irq = wp + min * GRCAN_MSG_SIZE;
910        /* wrap irq around */
911        if (irq >= size) {
912                irq_trunk = irq - size;
913        } else
914                irq_trunk = irq;
915
916        /* init IRQ HW */
917        pDev->regs->rx0irq = irq_trunk;
918
919        /* Clear pending Rx IRQ */
920        pDev->regs->picr = GRCAN_RXIRQ_IRQ;
921
922        wp = READ_REG(&pDev->regs->rx0wr);
923
924        /* Calculate messages available */
925        dataavail = grcan_hw_rxavail(rp, wp, size);
926
927        if (dataavail < min) {
928                /* Still empty, proceed with sleep - Turn on IRQ (unmask irq) */
929                pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_RXIRQ_IRQ;
930                wait = 1;
931        } else {
932                /* enough message has been received, abort sleep - don't unmask interrupt */
933                wait = 0;
934        }
[7b8a920]935        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]936
937        /* Wait for IRQ to fire only if has been triggered */
938        if (wait) {
[91541551]939                rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
940                /*
941                 * The semaphore is released either due to the expected IRQ
942                 * condition or by BUSOFF, AHBERROR or another thread calling
943                 * grcan_stop(). In either case, state2err[] has the correnct
944                 * return value.
945                 */
946                return state2err[pDev->started];
[bc40b4d]947        }
948
949        return 0;
[226455f]950}
951
[ee078c21]952/* Wait for TX circular buffer to have room for min CAN messagges. TXIRQ is used to pin
[2d3d8f96]953 * point the location of the CAN message corresponding to min.
[44b06ca]954 *
[ee078c21]955 * min must be at least WRAP_AROUND_TX_MSGS less than max buffer capacity
956 * (pDev->txbuf_size/GRCAN_MSG_SIZE) for this algo to work.
[226455f]957 */
[bc40b4d]958static int grcan_wait_txspace(struct grcan_priv *pDev, int min)
[226455f]959{
[2d3d8f96]960        int wait, state;
[bc40b4d]961        unsigned int irq, rp, wp, size, space_left;
962        unsigned int irq_trunk;
[7b8a920]963        SPIN_IRQFLAGS(oldLevel);
[bc40b4d]964
965        DBGC(DBG_TX, "\n");
966        /*FUNCDBG(); */
967
[7b8a920]968        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[2d3d8f96]969        state = pDev->started;
970        /* A bus off interrupt may have occured after checking pDev->started */
971        if (state != STATE_STARTED) {
972                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
973                if (state == STATE_BUSOFF) {
974                        DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
975                } else if (state == STATE_AHBERR) {
976                        DBGC(DBG_STATE, "cancelled due to a AHB error\n");
977                } else {
978                        DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n");
979                }
980                return state2err[state];
981        }
[bc40b4d]982
983        pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
984
985        size = READ_REG(&pDev->regs->tx0size);
986        wp = READ_REG(&pDev->regs->tx0wr);
987
988        rp = READ_REG(&pDev->regs->tx0rd);
989
990        /**** Calculate IRQ Pointer ****/
991        irq = rp + min * GRCAN_MSG_SIZE;
992        /* wrap irq around */
993        if (irq >= size) {
994                irq_trunk = irq - size;
995        } else
996                irq_trunk = irq;
997
998        /* trigger HW to do a IRQ when enough room in buffer */
999        pDev->regs->tx0irq = irq_trunk;
1000
1001        /* Clear pending Tx IRQ */
1002        pDev->regs->picr = GRCAN_TXIRQ_IRQ;
1003
1004        /* One problem, if HW already gone past IRQ place the IRQ will
1005         * never be received resulting in a thread hang. We check if so
1006         * before proceeding.
1007         *
1008         * has the HW already gone past the IRQ generation place?
1009         *  == does min fit info tx buffer?
1010         */
1011        rp = READ_REG(&pDev->regs->tx0rd);
1012
1013        space_left = grcan_hw_txspace(rp, wp, size);
1014
1015        if (space_left < min) {
1016                /* Still too full, proceed with sleep - Turn on IRQ (unmask irq) */
1017                pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXIRQ_IRQ;
1018                wait = 1;
1019        } else {
1020                /* There are enough room in buffer, abort wait - don't unmask interrupt */
1021                wait = 0;
1022        }
[7b8a920]1023        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]1024
1025        /* Wait for IRQ to fire only if it has been triggered */
1026        if (wait) {
[91541551]1027                rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1028                return state2err[pDev->started];
[bc40b4d]1029        }
1030
1031        /* At this point the TxIRQ has been masked, we ned not to mask it */
1032        return 0;
[226455f]1033}
1034
1035static int grcan_tx_flush(struct grcan_priv *pDev)
1036{
[2d3d8f96]1037        int wait, state;
[bc40b4d]1038        unsigned int rp, wp;
[7b8a920]1039        SPIN_IRQFLAGS(oldLevel);
[bc40b4d]1040        FUNCDBG();
1041
1042        /* loop until all data in circular buffer has been read by hw.
1043         * (write pointer != read pointer )
1044         *
1045         * Hardware doesn't update write pointer - we do
1046         */
1047        while (
1048                (wp = READ_REG(&pDev->regs->tx0wr)) !=
1049                (rp = READ_REG(&pDev->regs->tx0rd))
1050        ) {
1051                /* Wait for TX empty IRQ */
[7b8a920]1052                SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[2d3d8f96]1053                state = pDev->started;
1054
1055                /* A bus off interrupt may have occured after checking pDev->started */
1056                if (state != STATE_STARTED) {
1057                        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1058                        if (state == STATE_BUSOFF) {
1059                                DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
1060                        } else if (state == STATE_AHBERR) {
1061                                DBGC(DBG_STATE, "cancelled due to a AHB error\n");
1062                        } else {
1063                                DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n");
1064                        }
1065                        return state2err[state];
1066                }
1067
[bc40b4d]1068                /* Clear pending TXEmpty IRQ */
1069                pDev->regs->picr = GRCAN_TXEMPTY_IRQ;
1070
1071                if (wp != READ_REG(&pDev->regs->tx0rd)) {
1072                        /* Still not empty, proceed with sleep - Turn on IRQ (unmask irq) */
1073                        pDev->regs->imr =
1074                            READ_REG(&pDev->regs->imr) | GRCAN_TXEMPTY_IRQ;
1075                        wait = 1;
1076                } else {
1077                        /* TX fifo is empty */
1078                        wait = 0;
1079                }
[7b8a920]1080                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[bc40b4d]1081                if (!wait)
1082                        break;
1083
1084                /* Wait for IRQ to wake us */
[91541551]1085                rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1086                state = pDev->started;
1087                if (state != STATE_STARTED) {
1088                        return state2err[state];
[bc40b4d]1089                }
1090        }
1091        return 0;
[226455f]1092}
1093
1094static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx)
1095{
[3681925]1096        unsigned int adr;
1097        FUNCDBG();
1098
1099        if ( tx ) {
1100                adr = (unsigned int)pDev->txbuf_adr;
1101                if (adr & 0x1) {
1102                        /* User defined "remote" address. Translate it into
1103                         * a CPU accessible address
1104                         */
1105                        pDev->_tx_hw = (void *)(adr & ~0x1);
1106                        drvmgr_translate_check(
1107                                pDev->dev,
1108                                DMAMEM_TO_CPU,
1109                                (void *)pDev->_tx_hw,
1110                                (void **)&pDev->_tx,
1111                                pDev->txbuf_size);
1112                        pDev->tx = (struct grcan_msg *)pDev->_tx;
1113                } else {
1114                        if (adr == 0) {
[11f3b9a]1115                                pDev->_tx = grlib_malloc(pDev->txbuf_size +
[3681925]1116                                                   BUFFER_ALIGNMENT_NEEDS);
1117                                if (!pDev->_tx)
1118                                        return -1;
1119                        } else {
1120                                /* User defined "cou-local" address. Translate
1121                                 * it into a CPU accessible address
1122                                 */
1123                                pDev->_tx = (void *)adr;
1124                        }
1125                        /* Align TX buffer */
1126                        pDev->tx = (struct grcan_msg *)
1127                                   (((unsigned int)pDev->_tx +
1128                                   (BUFFER_ALIGNMENT_NEEDS-1)) &
1129                                   ~(BUFFER_ALIGNMENT_NEEDS-1));
1130
1131                        /* Translate address into an hardware accessible
1132                         * address
1133                         */
1134                        drvmgr_translate_check(
1135                                pDev->dev,
1136                                CPUMEM_TO_DMA,
1137                                (void *)pDev->tx,
1138                                (void **)&pDev->_tx_hw,
1139                                pDev->txbuf_size);
1140                }
1141        }
[226455f]1142
[3681925]1143        if ( rx ) {
1144                adr = (unsigned int)pDev->rxbuf_adr;
1145                if (adr & 0x1) {
1146                        /* User defined "remote" address. Translate it into
1147                         * a CPU accessible address
1148                         */
1149                        pDev->_rx_hw = (void *)(adr & ~0x1);
1150                        drvmgr_translate_check(
1151                                pDev->dev,
1152                                DMAMEM_TO_CPU,
1153                                (void *)pDev->_rx_hw,
1154                                (void **)&pDev->_rx,
1155                                pDev->rxbuf_size);
1156                        pDev->rx = (struct grcan_msg *)pDev->_rx;
1157                } else {
1158                        if (adr == 0) {
[11f3b9a]1159                                pDev->_rx = grlib_malloc(pDev->rxbuf_size +
[3681925]1160                                                   BUFFER_ALIGNMENT_NEEDS);
1161                                if (!pDev->_rx)
1162                                        return -1;
1163                        } else {
1164                                /* User defined "cou-local" address. Translate
1165                                 * it into a CPU accessible address
1166                                 */
1167                                pDev->_rx = (void *)adr;
1168                        }
1169                        /* Align RX buffer */
1170                        pDev->rx = (struct grcan_msg *)
1171                                   (((unsigned int)pDev->_rx +
1172                                   (BUFFER_ALIGNMENT_NEEDS-1)) &
1173                                   ~(BUFFER_ALIGNMENT_NEEDS-1));
1174
1175                        /* Translate address into an hardware accessible
1176                         * address
1177                         */
1178                        drvmgr_translate_check(
1179                                pDev->dev,
1180                                CPUMEM_TO_DMA,
1181                                (void *)pDev->rx,
1182                                (void **)&pDev->_rx_hw,
1183                                pDev->rxbuf_size);
1184                }
1185        }
1186        return 0;
[226455f]1187}
1188
1189static void grcan_free_buffers(struct grcan_priv *pDev, int rx, int tx)
1190{
[bc40b4d]1191        FUNCDBG();
1192
1193        if (tx && pDev->_tx) {
1194                free(pDev->_tx);
1195                pDev->_tx = NULL;
1196                pDev->tx = NULL;
1197        }
1198
1199        if (rx && pDev->_rx) {
1200                free(pDev->_rx);
1201                pDev->_rx = NULL;
1202                pDev->rx = NULL;
1203        }
[226455f]1204}
1205
[ad203e58]1206int grcan_dev_count(void)
[226455f]1207{
[ad203e58]1208        return grcan_count;
[226455f]1209}
1210
[ca4c4164]1211void *grcan_open_by_name(char *name, int *dev_no)
1212{
1213        int i;
1214        for (i = 0; i < grcan_count; i++){
1215                struct grcan_priv *pDev;
1216
1217                pDev = priv_tab[i];
1218                if (NULL == pDev) {
1219                        continue;
1220                }
1221                if (strncmp(pDev->devName, name, NELEM(pDev->devName)) == 0) {
1222                        if (dev_no)
1223                                *dev_no = i;
1224                        return grcan_open(i);
1225                }
1226        }
1227        return NULL;
1228}
1229
[ad203e58]1230void *grcan_open(int dev_no)
[3681925]1231{
1232        struct grcan_priv *pDev;
[ad203e58]1233        void *ret;
[3681925]1234        union drvmgr_key_value *value;
[44b06ca]1235
[3681925]1236        FUNCDBG();
[226455f]1237
[ad203e58]1238        if (grcan_count == 0 || (grcan_count <= dev_no)) {
1239                return NULL;
[3681925]1240        }
[ad203e58]1241
1242        pDev = priv_tab[dev_no];
[226455f]1243
[3681925]1244        /* Wait until we get semaphore */
1245        if (rtems_semaphore_obtain(pDev->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
1246            != RTEMS_SUCCESSFUL) {
[ad203e58]1247                return NULL;
[3681925]1248        }
[44b06ca]1249
[3681925]1250        /* is device busy/taken? */
1251        if ( pDev->open ) {
[ad203e58]1252                ret = NULL;
[3681925]1253                goto out;
1254        }
[226455f]1255
[7b8a920]1256        SPIN_INIT(&pDev->devlock, pDev->devName);
1257
[3681925]1258        /* Mark device taken */
1259        pDev->open = 1;
1260
1261        pDev->txblock = pDev->rxblock = 1;
1262        pDev->txcomplete = pDev->rxcomplete = 0;
[2d3d8f96]1263        pDev->started = STATE_STOPPED;
[3681925]1264        pDev->config_changed = 1;
1265        pDev->config.silent = 0;
1266        pDev->config.abort = 0;
1267        pDev->config.selection.selection = 0;
1268        pDev->config.selection.enable0 = 0;
1269        pDev->config.selection.enable1 = 1;
1270        pDev->flushing = 0;
1271        pDev->rx = pDev->_rx = NULL;
1272        pDev->tx = pDev->_tx = NULL;
1273        pDev->txbuf_adr = 0;
1274        pDev->rxbuf_adr = 0;
1275        pDev->txbuf_size = TX_BUF_SIZE;
1276        pDev->rxbuf_size = RX_BUF_SIZE;
1277
1278        /* Override default buffer sizes if available from bus resource */
[4d3e70f4]1279        value = drvmgr_dev_key_get(pDev->dev, "txBufSize", DRVMGR_KT_INT);
[3681925]1280        if ( value )
1281                pDev->txbuf_size = value->i;
1282
[4d3e70f4]1283        value = drvmgr_dev_key_get(pDev->dev, "rxBufSize", DRVMGR_KT_INT);
[3681925]1284        if ( value )
1285                pDev->rxbuf_size = value->i;
1286
[4d3e70f4]1287        value = drvmgr_dev_key_get(pDev->dev, "txBufAdr", DRVMGR_KT_POINTER);
[3681925]1288        if ( value )
1289                pDev->txbuf_adr = value->ptr;
1290
[4d3e70f4]1291        value = drvmgr_dev_key_get(pDev->dev, "rxBufAdr", DRVMGR_KT_POINTER);
[3681925]1292        if ( value )
1293                pDev->rxbuf_adr = value->ptr;
1294
1295        DBG("Defaulting to rxbufsize: %d, txbufsize: %d\n",RX_BUF_SIZE,TX_BUF_SIZE);
1296
1297        /* Default to accept all messages */
1298        pDev->afilter.mask = 0x00000000;
1299        pDev->afilter.code = 0x00000000;
1300
1301        /* Default to disable sync messages (only trigger when id is set to all ones) */
1302        pDev->sfilter.mask = 0xffffffff;
1303        pDev->sfilter.code = 0x00000000;
1304
1305        /* Calculate default timing register values */
1306        grcan_calc_timing(GRCAN_DEFAULT_BAUD,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&pDev->config.timing);
1307
1308        if ( grcan_alloc_buffers(pDev,1,1) ) {
[ad203e58]1309                ret = NULL;
[3681925]1310                goto out;
1311        }
[44b06ca]1312
[3681925]1313        /* Clear statistics */
1314        memset(&pDev->stats,0,sizeof(struct grcan_stats));
[44b06ca]1315
[ad203e58]1316        ret = pDev;
[226455f]1317out:
[3681925]1318        rtems_semaphore_release(pDev->dev_sem);
1319        return ret;
[226455f]1320}
1321
[ad203e58]1322int grcan_close(void *d)
[226455f]1323{
[ad203e58]1324        struct grcan_priv *pDev = d;
[44b06ca]1325
[3681925]1326        FUNCDBG();
[44b06ca]1327
[2d3d8f96]1328        grcan_stop(d);
[44b06ca]1329
[3681925]1330        grcan_hw_reset(pDev->regs);
[44b06ca]1331
[3681925]1332        grcan_free_buffers(pDev,1,1);
[226455f]1333
[3681925]1334        /* Mark Device as closed */
1335        pDev->open = 0;
1336
[ad203e58]1337        return 0;
[226455f]1338}
1339
[ad203e58]1340int grcan_read(void *d, CANMsg *msg, size_t ucount)
[226455f]1341{
[ad203e58]1342        struct grcan_priv *pDev = d;
[3681925]1343        CANMsg *dest;
1344        unsigned int count, left;
[2d3d8f96]1345        int nread;
[3681925]1346        int req_cnt;
[44b06ca]1347
[3681925]1348        FUNCDBG();
[226455f]1349
[ad203e58]1350        dest = msg;
1351        req_cnt = ucount;
[44b06ca]1352
[3681925]1353        if ( (!dest) || (req_cnt<1) )
[2d3d8f96]1354                return GRCAN_RET_INVARG;
[226455f]1355
[2d3d8f96]1356        if (pDev->started != STATE_STARTED) {
1357                return GRCAN_RET_NOTSTARTED;
1358        }
[44b06ca]1359
[2d3d8f96]1360        DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount);
[44b06ca]1361
[2d3d8f96]1362        nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt);
1363        if (nread < 0) {
1364                return nread;
1365        }
1366        count = nread;
[3681925]1367        if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){
1368                if ( count > 0 ) {
1369                        /* Successfully received messages (at least one) */
[ad203e58]1370                        return count;
[3681925]1371                }
[226455f]1372
[3681925]1373                /* nothing read, shall we block? */
1374                if ( !pDev->rxblock ) {
1375                        /* non-blocking mode */
[2d3d8f96]1376                        return GRCAN_RET_TIMEOUT;
[3681925]1377                }
1378        }
[44b06ca]1379
[bc40b4d]1380        while (count == 0 || (pDev->rxcomplete && (count!=req_cnt))) {
1381                if (!pDev->rxcomplete) {
1382                        left = 1; /* return as soon as there is one message available */
1383                } else {
1384                        left = req_cnt - count;     /* return as soon as all data are available */
[44b06ca]1385
[bc40b4d]1386                        /* never wait for more than the half the maximum size of the receive buffer
1387                         * Why? We need some time to copy buffer before to catch up with hw,
1388                         * otherwise we would have to copy everything when the data has been
1389                         * received.
1390                         */
1391                        if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){
1392                                left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2;
1393                        }
[3681925]1394                }
1395
[2d3d8f96]1396                nread = grcan_wait_rxdata(pDev, left);
1397                if (nread) {
[bc40b4d]1398                        /* The wait has been aborted, probably due to
1399                         * the device driver has been closed by another
[2d3d8f96]1400                         * thread or a bus-off. Return error code.
[bc40b4d]1401                         */
[2d3d8f96]1402                        return nread;
[bc40b4d]1403                }
[3681925]1404
[bc40b4d]1405                /* Try read bytes from circular buffer */
[2d3d8f96]1406                nread = grcan_hw_read_try(
[bc40b4d]1407                                pDev,
1408                                pDev->regs,
1409                                dest+count,
1410                                req_cnt-count);
[2d3d8f96]1411
1412                if (nread < 0) {
1413                        /* The read was aborted by bus-off. */
1414                        return nread;
1415                }
1416                count += nread;
[3681925]1417        }
1418        /* no need to unmask IRQ as IRQ Handler do that for us. */
[ad203e58]1419        return count;
[226455f]1420}
[44b06ca]1421
[ad203e58]1422int grcan_write(void *d, CANMsg *msg, size_t ucount)
[226455f]1423{
[ad203e58]1424        struct grcan_priv *pDev = d;
[3681925]1425        CANMsg *source;
1426        unsigned int count, left;
[2d3d8f96]1427        int nwritten;
[3681925]1428        int req_cnt;
[44b06ca]1429
[3681925]1430        DBGC(DBG_TX,"\n");
[44b06ca]1431
[2d3d8f96]1432        if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing)
1433                return GRCAN_RET_NOTSTARTED;
[44b06ca]1434
[ad203e58]1435        req_cnt = ucount;
1436        source = (CANMsg *) msg;
[44b06ca]1437
[3681925]1438        /* check proper length and buffer pointer */
1439        if (( req_cnt < 1) || (source == NULL) ){
[2d3d8f96]1440                return GRCAN_RET_INVARG;
[3681925]1441        }
[44b06ca]1442
[2d3d8f96]1443        nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt);
1444        if (nwritten < 0) {
1445                return nwritten;
1446        }
1447        count = nwritten;
[3681925]1448        if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) {
1449                if ( count > 0 ) {
1450                        /* Successfully transmitted chars (at least one char) */
[ad203e58]1451                        return count;
[3681925]1452                }
[44b06ca]1453
[3681925]1454                /* nothing written, shall we block? */
1455                if ( !pDev->txblock ) {
1456                        /* non-blocking mode */
[2d3d8f96]1457                        return GRCAN_RET_TIMEOUT;
[3681925]1458                }
1459        }
[44b06ca]1460
[3681925]1461        /* if in txcomplete mode we need to transmit all chars */
1462        while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){
1463                /*** block until room to fit all or as much of transmit buffer as possible
1464                 * IRQ comes. Set up a valid IRQ point so that an IRQ is received
1465                 * when we can put a chunk of data into transmit fifo
1466                 */
1467                if ( !pDev->txcomplete ){
1468                        left = 1; /* wait for anything to fit buffer */
1469                }else{
1470                        left = req_cnt - count; /* wait for all data to fit in buffer */
1471
1472                        /* never wait for more than the half the maximum size of the transmit
1473                         * buffer
1474                         * Why? We need some time to fill buffer before hw catches up.
1475                         */
1476                        if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){
1477                                left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2;
1478                        }
1479                }
[44b06ca]1480
[2d3d8f96]1481                nwritten = grcan_wait_txspace(pDev,left);
[3681925]1482                /* Wait until more room in transmit buffer */
[2d3d8f96]1483                if ( nwritten ) {
[3681925]1484                        /* The wait has been aborted, probably due to
1485                         * the device driver has been closed by another
1486                         * thread. To avoid deadlock we return directly
1487                         * with error status.
1488                         */
[2d3d8f96]1489                        return nwritten;
[3681925]1490                }
[44b06ca]1491
[3681925]1492                /* Try read bytes from circular buffer */
[2d3d8f96]1493                nwritten = grcan_hw_write_try(
[3681925]1494                        pDev,
1495                        pDev->regs,
1496                        source+count,
1497                        req_cnt-count);
[2d3d8f96]1498
1499                if (nwritten < 0) {
1500                        /* Write was aborted by bus-off. */
1501                        return nwritten;
1502                }
1503                count += nwritten;
[3681925]1504        }
1505        /* no need to unmask IRQ as IRQ Handler do that for us. */
[44b06ca]1506
[ad203e58]1507        return count;
[226455f]1508}
1509
[ad203e58]1510int grcan_start(void *d)
[226455f]1511{
[ad203e58]1512        struct grcan_priv *pDev = d;
[3681925]1513
1514        FUNCDBG();
1515
[2d3d8f96]1516        if (grcan_get_state(d) == STATE_STARTED) {
[ad203e58]1517                return -1;
[2d3d8f96]1518        }
[ad203e58]1519
[2d3d8f96]1520        if ( (grcan_hw_start(pDev)) != RTEMS_SUCCESSFUL ){
[ad203e58]1521                return -2;
[3681925]1522        }
[44b06ca]1523
[91541551]1524        /* Clear semaphore state. This is to avoid effects from previous
1525         * bus-off/stop where semahpores where flushed() but the count remained.
1526         */
1527        rtems_semaphore_obtain(pDev->rx_sem, RTEMS_NO_WAIT, 0);
1528        rtems_semaphore_obtain(pDev->tx_sem, RTEMS_NO_WAIT, 0);
1529        rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_NO_WAIT, 0);
1530
[ad203e58]1531        /* Read and write are now open... */
[2d3d8f96]1532        pDev->started = STATE_STARTED;
1533        DBGC(DBG_STATE, "STOPPED|BUSOFF|AHBERR->STARTED\n");
[44b06ca]1534
[ad203e58]1535        /* Register interrupt routine and enable IRQ at IRQ ctrl */
[ca4c4164]1536        drvmgr_interrupt_register(pDev->dev, 0, pDev->devName,
1537                                        grcan_interrupt, pDev);
[226455f]1538
[ad203e58]1539        return 0;
1540}
[44b06ca]1541
[ad203e58]1542int grcan_stop(void *d)
1543{
1544        struct grcan_priv *pDev = d;
[2d3d8f96]1545        SPIN_IRQFLAGS(oldLevel);
[9855690]1546        int do_sw_stop;
[44b06ca]1547
[ad203e58]1548        FUNCDBG();
[44b06ca]1549
[2d3d8f96]1550        if (pDev->started == STATE_STOPPED)
[ad203e58]1551                return -1;
[44b06ca]1552
[2d3d8f96]1553        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1554        if (pDev->started == STATE_STARTED) {
1555                grcan_hw_stop(pDev);
[9855690]1556                do_sw_stop = 1;
[2d3d8f96]1557                DBGC(DBG_STATE, "STARTED->STOPPED\n");
1558        } else {
1559                /*
1560                 * started == STATE_[STOPPED|BUSOFF|AHBERR] so grcan_hw_stop()
1561                 * might already been called from ISR.
1562                 */
1563                DBGC(DBG_STATE, "[STOPPED|BUSOFF|AHBERR]->STOPPED\n");
[9855690]1564                do_sw_stop = 0;
[2d3d8f96]1565        }
1566        pDev->started = STATE_STOPPED;
1567        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1568
[9855690]1569        if (do_sw_stop)
1570                grcan_sw_stop(pDev);
1571
[ad203e58]1572        /* Disable interrupts */
1573        drvmgr_interrupt_unregister(pDev->dev, 0, grcan_interrupt, pDev);
[44b06ca]1574
[ad203e58]1575        return 0;
1576}
[3681925]1577
[2d3d8f96]1578int grcan_get_state(void *d)
[ad203e58]1579{
1580        struct grcan_priv *pDev = d;
[3681925]1581
[ad203e58]1582        FUNCDBG();
[44b06ca]1583
[ad203e58]1584        return pDev->started;
1585}
[44b06ca]1586
[ad203e58]1587int grcan_flush(void *d)
1588{
1589        struct grcan_priv *pDev = d;
1590        int tmp;
[226455f]1591
[ad203e58]1592        FUNCDBG();
1593
[2d3d8f96]1594        if ((pDev->started != STATE_STARTED) || pDev->flushing || pDev->config.silent)
[ad203e58]1595                return -1;
1596
1597        pDev->flushing = 1;
1598        tmp = grcan_tx_flush(pDev);
1599        pDev->flushing = 0;
1600        if ( tmp ) {
1601                /* The wait has been aborted, probably due to
1602                 * the device driver has been closed by another
1603                 * thread.
[3681925]1604                 */
[ad203e58]1605                return -1;
1606        }
[3681925]1607
[ad203e58]1608        return 0;
1609}
1610
1611int grcan_set_silent(void* d, int silent)
1612{
1613        struct grcan_priv *pDev = d;
1614
1615        FUNCDBG();
1616
[2d3d8f96]1617        if (pDev->started == STATE_STARTED)
[ad203e58]1618                return -1;
1619
1620        pDev->config.silent = silent;
1621        pDev->config_changed = 1;
1622
1623        return 0;
1624}
1625
1626int grcan_set_abort(void* d, int abort)
1627{
1628        struct grcan_priv *pDev = d;
1629
1630        FUNCDBG();
1631
[2d3d8f96]1632        if (pDev->started == STATE_STARTED)
[ad203e58]1633                return -1;
1634
1635        pDev->config.abort = abort;
1636        /* This Configuration parameter doesn't need HurriCANe reset
1637         * ==> no pDev->config_changed = 1;
1638         */
1639
1640        return 0;
1641}
1642
1643int grcan_set_selection(void *d, const struct grcan_selection *selection)
1644{
1645        struct grcan_priv *pDev = d;
1646
1647        FUNCDBG();
1648
[2d3d8f96]1649        if (pDev->started == STATE_STARTED)
[ad203e58]1650                return -1;
1651
1652        if ( !selection )
1653                return -2;
1654
1655        pDev->config.selection = *selection;
1656        pDev->config_changed = 1;
1657
1658        return 0;
1659}
1660
1661int grcan_set_rxblock(void *d, int block)
1662{
1663        struct grcan_priv *pDev = d;
1664
1665        FUNCDBG();
1666
1667        pDev->rxblock = block;
1668
1669        return 0;
1670}
1671
1672int grcan_set_txblock(void *d, int block)
1673{
1674        struct grcan_priv *pDev = d;
1675
1676        FUNCDBG();
1677
1678        pDev->txblock = block;
1679
1680        return 0;
1681}
1682
1683int grcan_set_txcomplete(void *d, int complete)
1684{
1685        struct grcan_priv *pDev = d;
1686
1687        FUNCDBG();
1688
1689        pDev->txcomplete = complete;
1690
1691        return 0;
1692}
1693
1694int grcan_set_rxcomplete(void *d, int complete)
1695{
1696        struct grcan_priv *pDev = d;
1697
1698        FUNCDBG();
1699
1700        pDev->rxcomplete = complete;
1701
1702        return 0;
1703}
1704
1705int grcan_get_stats(void *d, struct grcan_stats *stats)
1706{
1707        struct grcan_priv *pDev = d;
[c297060]1708        SPIN_IRQFLAGS(oldLevel);
[ad203e58]1709
1710        FUNCDBG();
1711
1712        if ( !stats )
1713                return -1;
1714
[c297060]1715        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1716        *stats = pDev->stats;
[c297060]1717        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1718
1719        return 0;
1720}
1721
1722int grcan_clr_stats(void *d)
1723{
1724        struct grcan_priv *pDev = d;
[7b8a920]1725        SPIN_IRQFLAGS(oldLevel);
[ad203e58]1726
1727        FUNCDBG();
1728
[7b8a920]1729        SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1730        memset(&pDev->stats,0,sizeof(struct grcan_stats));
[7b8a920]1731        SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1732
1733        return 0;
1734}
1735
1736int grcan_set_speed(void *d, unsigned int speed)
1737{
1738        struct grcan_priv *pDev = d;
1739        struct grcan_timing timing;
1740        int ret;
1741
1742        FUNCDBG();
1743
1744        /* cannot change speed during run mode */
[2d3d8f96]1745        if (pDev->started == STATE_STARTED)
[ad203e58]1746                return -1;
1747
1748        /* get speed rate from argument */
1749        ret = grcan_calc_timing(speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, &timing);
1750        if ( ret )
1751                return -2;
1752
1753        /* save timing/speed */
1754        pDev->config.timing = timing;
1755        pDev->config_changed = 1;
1756
1757        return 0;
1758}
1759
1760int grcan_set_btrs(void *d, const struct grcan_timing *timing)
1761{
1762        struct grcan_priv *pDev = d;
1763
1764        FUNCDBG();
1765
1766        /* Set BTR registers manually
1767         * Read GRCAN/HurriCANe Manual.
1768         */
[2d3d8f96]1769        if (pDev->started == STATE_STARTED)
[ad203e58]1770                return -1;
1771
1772        if ( !timing )
1773                return -2;
1774
1775        pDev->config.timing = *timing;
1776        pDev->config_changed = 1;
1777
1778        return 0;
1779}
1780
1781int grcan_set_afilter(void *d, const struct grcan_filter *filter)
1782{
1783        struct grcan_priv *pDev = d;
1784
1785        FUNCDBG();
1786
1787        if ( !filter ){
1788                /* Disable filtering - let all messages pass */
1789                pDev->afilter.mask = 0x0;
1790                pDev->afilter.code = 0x0;
1791        }else{
1792                /* Save filter */
1793                pDev->afilter = *filter;
[3681925]1794        }
[ad203e58]1795        /* Set hardware acceptance filter */
1796        grcan_hw_accept(pDev->regs,&pDev->afilter);
1797
1798        return 0;
1799}
1800
1801int grcan_set_sfilter(void *d, const struct grcan_filter *filter)
1802{
1803        struct grcan_priv *pDev = d;
[05749690]1804        SPIN_IRQFLAGS(oldLevel);
[ad203e58]1805
1806        FUNCDBG();
1807
1808        if ( !filter ){
1809                /* disable TX/RX SYNC filtering */
1810                pDev->sfilter.mask = 0xffffffff;
1811                pDev->sfilter.mask = 0;
1812
1813                 /* disable Sync interrupt */
[05749690]1814                SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1815                pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~(GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
[05749690]1816                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1817        }else{
1818                /* Save filter */
1819                pDev->sfilter = *filter;
1820
1821                /* Enable Sync interrupt */
[05749690]1822                SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1823                pDev->regs->imr = READ_REG(&pDev->regs->imr) | (GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
[05749690]1824                SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
[ad203e58]1825        }
1826        /* Set Sync RX/TX filter */
1827        grcan_hw_sync(pDev->regs,&pDev->sfilter);
1828
1829        return 0;
1830}
1831
1832int grcan_get_status(void* d, unsigned int *data)
1833{
1834        struct grcan_priv *pDev = d;
1835
1836        FUNCDBG();
1837
1838        if ( !data )
1839                return -1;
1840
1841        /* Read out the statsu register from the GRCAN core */
1842        data[0] = READ_REG(&pDev->regs->stat);
1843
1844        return 0;
[226455f]1845}
1846
[2d3d8f96]1847/* Error indicators */
1848#define GRCAN_IRQ_ERRORS \
1849                (GRCAN_RXAHBERR_IRQ | GRCAN_TXAHBERR_IRQ | GRCAN_OFF_IRQ)
1850#define GRCAN_STAT_ERRORS (GRCAN_STAT_AHBERR | GRCAN_STAT_OFF)
1851/* Warning & RX/TX sync indicators */
1852#define GRCAN_IRQ_WARNS \
1853                (GRCAN_ERR_IRQ | GRCAN_OR_IRQ | GRCAN_TXLOSS_IRQ | \
1854                 GRCAN_RXSYNC_IRQ | GRCAN_TXSYNC_IRQ)
1855#define GRCAN_STAT_WARNS (GRCAN_STAT_OR | GRCAN_STAT_PASS)
1856
[226455f]1857/* Handle the IRQ */
[3681925]1858static void grcan_interrupt(void *arg)
[226455f]1859{
[3681925]1860        struct grcan_priv *pDev = arg;
1861        unsigned int status = READ_REG(&pDev->regs->pimsr);
1862        unsigned int canstat = READ_REG(&pDev->regs->stat);
[2d3d8f96]1863        unsigned int imr_clear;
[05749690]1864        SPIN_ISR_IRQFLAGS(irqflags);
[44b06ca]1865
[3681925]1866        /* Spurious IRQ call? */
1867        if ( !status && !canstat )
1868                return;
[44b06ca]1869
[2d3d8f96]1870        if (pDev->started != STATE_STARTED) {
1871                DBGC(DBG_STATE, "not STARTED (unexpected interrupt)\n");
1872                pDev->regs->picr = status;
1873                return;
[3681925]1874        }
[226455f]1875
[2d3d8f96]1876        FUNCDBG();
1877
1878        if ( (status & GRCAN_IRQ_ERRORS) || (canstat & GRCAN_STAT_ERRORS) ) {
1879                /* Bus-off condition interrupt
[3681925]1880                 * The link is brought down by hardware, we wake all threads
1881                 * that is blocked in read/write calls and stop futher calls
1882                 * to read/write until user has called ioctl(fd,START,0).
1883                 */
[05749690]1884                SPIN_LOCK(&pDev->devlock, irqflags);
[2d3d8f96]1885                DBGC(DBG_STATE, "STARTED->BUSOFF|AHBERR\n");
1886                pDev->stats.ints++;
1887                if ((status & GRCAN_OFF_IRQ) || (canstat & GRCAN_STAT_OFF)) {
1888                        /* CAN Bus-off interrupt */
1889                        DBGC(DBG_STATE, "BUSOFF: status: 0x%x, canstat: 0x%x\n",
1890                                status, canstat);
1891                        pDev->started = STATE_BUSOFF;
1892                        pDev->stats.busoff_cnt++;
1893                } else {
1894                        /* RX or Tx AHB Error interrupt */
1895                        printk("AHBERROR: status: 0x%x, canstat: 0x%x\n",
1896                                status, canstat);
1897                        pDev->started = STATE_AHBERR;
1898                        pDev->stats.ahberr_cnt++;
1899                }
[ad203e58]1900                grcan_hw_stop(pDev); /* this mask all IRQ sources */
[2d3d8f96]1901                pDev->regs->picr = 0x1ffff; /* clear all interrupts */
1902                /*
1903                 * Prevent driver from affecting bus. Driver can be started
1904                 * again with grcan_start().
1905                 */
[05749690]1906                SPIN_UNLOCK(&pDev->devlock, irqflags);
[9855690]1907
[91541551]1908                /* Release semaphores to wake blocked threads. */
[9855690]1909                grcan_sw_stop(pDev);
1910
[2d3d8f96]1911                /*
1912                 * NOTE: Another interrupt may be pending now so ISR could be
1913                 * executed one more time aftert this (first) return.
1914                 */
1915                return;
[3681925]1916        }
[44b06ca]1917
[2d3d8f96]1918        /* Mask interrupts in one place under spin-lock. */
1919        imr_clear = status & (GRCAN_RXIRQ_IRQ | GRCAN_TXIRQ_IRQ | GRCAN_TXEMPTY_IRQ);
[44b06ca]1920
[2d3d8f96]1921        SPIN_LOCK(&pDev->devlock, irqflags);
[44b06ca]1922
[2d3d8f96]1923        /* Increment number of interrupts counter */
1924        pDev->stats.ints++;
1925        if ((status & GRCAN_IRQ_WARNS) || (canstat & GRCAN_STAT_WARNS)) {
[44b06ca]1926
[2d3d8f96]1927                if ( (status & GRCAN_ERR_IRQ) || (canstat & GRCAN_STAT_PASS) ) {
1928                        /* Error-Passive interrupt */
1929                        pDev->stats.passive_cnt++;
1930                }
1931
1932                if ( (status & GRCAN_OR_IRQ) || (canstat & GRCAN_STAT_OR) ) {
1933                        /* Over-run during reception interrupt */
1934                        pDev->stats.overrun_cnt++;
1935                }
1936
1937                if ( status & GRCAN_TXLOSS_IRQ ) {
1938                        pDev->stats.txloss_cnt++;
1939                }
1940
1941                if ( status & GRCAN_TXSYNC_IRQ ) {
1942                        /* TxSync message transmitted interrupt */
1943                        pDev->stats.txsync_cnt++;
1944                }
1945
1946                if ( status & GRCAN_RXSYNC_IRQ ) {
1947                        /* RxSync message received interrupt */
1948                        pDev->stats.rxsync_cnt++;
1949                }
[3681925]1950        }
[44b06ca]1951
[2d3d8f96]1952        if (imr_clear) {
1953                pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~imr_clear;
1954
[05749690]1955                SPIN_UNLOCK(&pDev->devlock, irqflags);
[44b06ca]1956
[2d3d8f96]1957                if ( status & GRCAN_RXIRQ_IRQ ) {
1958                        /* RX IRQ pointer interrupt */
1959                        rtems_semaphore_release(pDev->rx_sem);
1960                }
[44b06ca]1961
[2d3d8f96]1962                if ( status & GRCAN_TXIRQ_IRQ ) {
1963                        /* TX IRQ pointer interrupt */
1964                        rtems_semaphore_release(pDev->tx_sem);
1965                }
[44b06ca]1966
[2d3d8f96]1967                if (status & GRCAN_TXEMPTY_IRQ ) {
1968                        rtems_semaphore_release(pDev->txempty_sem);
1969                }
1970        } else {
[05749690]1971                SPIN_UNLOCK(&pDev->devlock, irqflags);
[3681925]1972        }
[44b06ca]1973
[3681925]1974        /* Clear IRQs */
1975        pDev->regs->picr = status;
[226455f]1976}
Note: See TracBrowser for help on using the repository browser.