Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  GRCAN driver
0005  *
0006  *  COPYRIGHT (c) 2007-2019.
0007  *  Cobham Gaisler AB.
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 #include <bsp.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <assert.h>
0036 #include <ctype.h>
0037 #include <rtems/bspIo.h>
0038 
0039 #include <grlib/grcan.h>
0040 #include <grlib/canbtrs.h>
0041 #include <drvmgr/drvmgr.h>
0042 #include <grlib/ambapp_bus.h>
0043 #include <grlib/ambapp.h>
0044 
0045 #include <grlib/grlib_impl.h>
0046 #include "grcan_internal.h"
0047 
0048 /* Maximum number of GRCAN devices supported by driver */
0049 #define GRCAN_COUNT_MAX 8
0050 
0051 #define BLOCK_SIZE (16*4)
0052 
0053 /* grcan needs to have it buffers aligned to 1k boundaries */
0054 #define BUFFER_ALIGNMENT_NEEDS 1024
0055 
0056 /* Default Maximium buffer size for statically allocated buffers */
0057 #ifndef TX_BUF_SIZE
0058  #define TX_BUF_SIZE (BLOCK_SIZE*16)
0059 #endif
0060 
0061 /* Make receiver buffers bigger than transmitt */
0062 #ifndef RX_BUF_SIZE
0063  #define RX_BUF_SIZE ((3*BLOCK_SIZE)*16)
0064 #endif
0065 
0066 #ifndef IRQ_CLEAR_PENDING
0067  #define IRQ_CLEAR_PENDING(irqno)
0068 #endif
0069 
0070 #ifndef IRQ_UNMASK
0071  #define IRQ_UNMASK(irqno)
0072 #endif
0073 
0074 #ifndef IRQ_MASK
0075  #define IRQ_MASK(irqno)
0076 #endif
0077 
0078 /* Uncomment for debug output */
0079 /****************** DEBUG Definitions ********************/
0080 #define DBG_TX 2
0081 #define DBG_RX 4
0082 #define DBG_STATE 8
0083 
0084 #define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX )
0085 /*
0086 #define DEBUG
0087 #define DEBUGFUNCS
0088 */
0089 #include <grlib/debug_defs.h>
0090 
0091 /*********************************************************/
0092 
0093 int state2err[4] = {
0094     /* STATE_STOPPED */ GRCAN_RET_NOTSTARTED,
0095     /* STATE_STARTED */ GRCAN_RET_OK,
0096     /* STATE_BUSOFF  */ GRCAN_RET_BUSOFF,
0097     /* STATE_AHBERR  */ GRCAN_RET_AHBERR
0098 };
0099 
0100 static void __inline__ grcan_hw_reset(struct grcan_regs *regs);
0101 
0102 static void grcan_hw_config(
0103     struct grcan_priv *pDev,
0104     struct grcan_config *conf);
0105 
0106 static void grcan_hw_accept(
0107     struct grcan_regs *regs,
0108     struct grcan_filter *afilter);
0109 
0110 static void grcan_hw_sync(
0111     struct grcan_regs *regs,
0112     struct grcan_filter *sfilter);
0113 
0114 static void grcan_interrupt(void *arg);
0115 
0116 #define NELEM(a) ((int) (sizeof (a) / sizeof (a[0])))
0117 
0118 /* GRCAN nominal boundaries for baud-rate paramters */
0119 struct grlib_canbtrs_ranges grcan_btrs_ranges = {
0120     .max_scaler = 256*8, /* scaler is multiplied by BPR in steps 1,2,4,8 */
0121     .has_bpr = 1,
0122     .divfactor = 2,
0123     .min_tseg1 = 1,
0124     .max_tseg1 = 15,
0125     .min_tseg2 = 2,
0126     .max_tseg2 = 8,
0127 };
0128 
0129 /* GRCANFD nominal boundaries */
0130 struct grlib_canbtrs_ranges grcanfd_nom_btrs_ranges = {
0131     .max_scaler = 256,
0132     .has_bpr = 0,
0133     .divfactor = 1,
0134     .min_tseg1 = 2,
0135     .max_tseg1 = 63,
0136     .min_tseg2 = 2,
0137     .max_tseg2 = 16,
0138 };
0139 
0140 /* GRCANFD flexible baud-rate boundaries */
0141 struct grlib_canbtrs_ranges grcanfd_fd_btrs_ranges = {
0142     .max_scaler = 256,
0143     .has_bpr = 0,
0144     .divfactor = 1,
0145     .min_tseg1 = 1,
0146     .max_tseg1 = 15,
0147     .min_tseg2 = 2,
0148     .max_tseg2 = 8,
0149 };
0150 
0151 static int grcan_count = 0;
0152 static struct grcan_priv *priv_tab[GRCAN_COUNT_MAX];
0153 
0154 /******************* Driver manager interface ***********************/
0155 
0156 /* Driver prototypes */
0157 int grcan_device_init(struct grcan_priv *pDev);
0158 
0159 int grcan_init2(struct drvmgr_dev *dev);
0160 int grcan_init3(struct drvmgr_dev *dev);
0161 
0162 struct drvmgr_drv_ops grcan_ops = 
0163 {
0164     .init = {NULL, grcan_init2, grcan_init3, NULL},
0165     .remove = NULL,
0166     .info = NULL
0167 };
0168 
0169 struct amba_dev_id grcan_ids[] = 
0170 {
0171     {VENDOR_GAISLER, GAISLER_GRCAN},
0172     {VENDOR_GAISLER, GAISLER_GRHCAN},
0173     {VENDOR_GAISLER, GAISLER_GRCANFD},
0174     {0, 0}      /* Mark end of table */
0175 };
0176 
0177 struct amba_drv_info grcan_drv_info =
0178 {
0179     {
0180         DRVMGR_OBJ_DRV,         /* Driver */
0181         NULL,               /* Next driver */
0182         NULL,               /* Device list */
0183         DRIVER_AMBAPP_GAISLER_GRCAN_ID, /* Driver ID */
0184         "GRCAN_DRV",            /* Driver Name */
0185         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0186         &grcan_ops,
0187         NULL,               /* Funcs */
0188         0,              /* No devices yet */
0189         0,
0190     },
0191     &grcan_ids[0]
0192 };
0193 
0194 void grcan_register_drv (void)
0195 {
0196     DBG("Registering GRCAN driver\n");
0197     drvmgr_drv_register(&grcan_drv_info.general);
0198 }
0199 
0200 int grcan_init2(struct drvmgr_dev *dev)
0201 {
0202     struct grcan_priv *priv;
0203 
0204     DBG("GRCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0205     if (GRCAN_COUNT_MAX <= grcan_count)
0206         return DRVMGR_ENORES;
0207     priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0208     if ( !priv )
0209         return DRVMGR_NOMEM;
0210     priv->dev = dev;
0211 
0212     /* This core will not find other cores, so we wait for init2() */
0213 
0214     return DRVMGR_OK;
0215 }
0216 
0217 int grcan_init3(struct drvmgr_dev *dev)
0218 {
0219     struct grcan_priv *priv;
0220     char prefix[32];
0221 
0222     priv = dev->priv;
0223 
0224     /*
0225      * Now we take care of device initialization.
0226      */
0227 
0228     if ( grcan_device_init(priv) ) {
0229         return DRVMGR_FAIL;
0230     }
0231 
0232     priv_tab[grcan_count] = priv;
0233     grcan_count++;
0234 
0235     /* Get Filesystem name prefix */
0236     prefix[0] = '\0';
0237     if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0238         /* Failed to get prefix, make sure of a unique FS name
0239          * by using the driver minor.
0240          */
0241         sprintf(priv->devName, "grcan%d", dev->minor_drv);
0242     } else {
0243         /* Got special prefix, this means we have a bus prefix
0244          * And we should use our "bus minor"
0245          */
0246         sprintf(priv->devName, "%sgrcan%d", prefix, dev->minor_bus);
0247     }
0248 
0249     return DRVMGR_OK;
0250 }
0251 
0252 int grcan_device_init(struct grcan_priv *pDev)
0253 {
0254     struct amba_dev_info *ambadev;
0255     struct ambapp_core *pnpinfo;
0256 
0257     /* Get device information from AMBA PnP information */
0258     ambadev = (struct amba_dev_info *)pDev->dev->businfo;
0259     if ( ambadev == NULL ) {
0260         return -1;
0261     }
0262     pnpinfo = &ambadev->info;
0263     pDev->irq = pnpinfo->irq;
0264     pDev->regs = (struct grcan_regs *)pnpinfo->apb_slv->start;
0265     pDev->minor = pDev->dev->minor_drv;
0266     if (ambadev->id.device == GAISLER_GRCANFD)
0267         pDev->fd_capable = 1;
0268 
0269     /* Get frequency in Hz */
0270     if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->corefreq_hz) ) {
0271         return -1;
0272     }
0273 
0274     DBG("GRCAN frequency: %d Hz\n", pDev->corefreq_hz);
0275 
0276     /* Reset Hardware before attaching IRQ handler */
0277     grcan_hw_reset(pDev->regs);
0278 
0279     /* RX Semaphore created with count = 0 */
0280     if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'R', '0' + pDev->minor),
0281         0,
0282         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0283         RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0284         0,
0285         &pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
0286         return RTEMS_INTERNAL_ERROR;
0287     }
0288 
0289     /* TX Semaphore created with count = 0 */
0290     if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'T', '0' + pDev->minor),
0291         0,
0292         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0293         RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0294         0,
0295         &pDev->tx_sem) != RTEMS_SUCCESSFUL ) {
0296         return RTEMS_INTERNAL_ERROR;
0297     }
0298 
0299     /* TX Empty Semaphore created with count = 0 */
0300     if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'E', '0' + pDev->minor),
0301         0,
0302         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0303         RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0304         0,
0305         &pDev->txempty_sem) != RTEMS_SUCCESSFUL ) {
0306         return RTEMS_INTERNAL_ERROR;
0307     }
0308 
0309     /* Device Semaphore created with count = 1 */
0310     if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'A', '0' + pDev->minor),
0311         1,
0312         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0313         RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
0314         0,
0315         &pDev->dev_sem) != RTEMS_SUCCESSFUL ) {
0316         return RTEMS_INTERNAL_ERROR;
0317     }
0318 
0319     return 0;
0320 }
0321 
0322 static void __inline__ grcan_hw_reset(struct grcan_regs *regs)
0323 {
0324     regs->ctrl = GRCAN_CTRL_RESET;
0325 }
0326 
0327 static rtems_device_driver grcan_hw_start(struct grcan_priv *pDev)
0328 {
0329     /*
0330      * tmp is set but never used. GCC gives a warning for this
0331      * and we need to tell GCC not to complain.
0332      */
0333     unsigned int tmp RTEMS_UNUSED;
0334 
0335     SPIN_IRQFLAGS(oldLevel);
0336 
0337     FUNCDBG();
0338 
0339     /* Check that memory has been allocated successfully */
0340     if (!pDev->tx || !pDev->rx)
0341         return RTEMS_NO_MEMORY;
0342 
0343     /* Configure FIFO configuration register
0344      * and Setup timing
0345      */
0346     if (pDev->config_changed) {
0347         grcan_hw_config(pDev, &pDev->config);
0348         pDev->config_changed = 0;
0349     }
0350 
0351     /* Setup receiver */
0352     pDev->regs->rx0addr = (unsigned int)pDev->_rx_hw;
0353     pDev->regs->rx0size = pDev->rxbuf_size;
0354 
0355     /* Setup Transmitter */
0356     pDev->regs->tx0addr = (unsigned int)pDev->_tx_hw;
0357     pDev->regs->tx0size = pDev->txbuf_size;
0358 
0359     /* Setup acceptance filters */
0360     grcan_hw_accept(pDev->regs, &pDev->afilter);
0361 
0362     /* Sync filters */
0363     grcan_hw_sync(pDev->regs, &pDev->sfilter);
0364 
0365     /* Clear status bits */
0366     tmp = READ_REG(&pDev->regs->stat);
0367     pDev->regs->stat = 0;
0368 
0369     /* Setup IRQ handling */
0370 
0371     /* Clear all IRQs */
0372     tmp = READ_REG(&pDev->regs->pir);
0373     pDev->regs->picr = 0x1ffff;
0374 
0375     /* unmask TxLoss|TxErrCntr|RxErrCntr|TxAHBErr|RxAHBErr|OR|OFF|PASS */
0376     pDev->regs->imr = 0x1601f;
0377 
0378     /* Enable routing of the IRQs */
0379     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0380     IRQ_UNMASK(pDev->irq + GRCAN_IRQ_TXSYNC);
0381     IRQ_UNMASK(pDev->irq + GRCAN_IRQ_RXSYNC);
0382     IRQ_UNMASK(pDev->irq + GRCAN_IRQ_IRQ);
0383     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0384 
0385     /* Enable receiver/transmitter */
0386     pDev->regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
0387     pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
0388 
0389     /* Enable HurriCANe core */
0390     pDev->regs->ctrl = GRCAN_CTRL_ENABLE;
0391 
0392     /* Leave transmitter disabled, it is enabled when
0393      * trying to send something.
0394      */
0395     return RTEMS_SUCCESSFUL;
0396 }
0397 
0398 static void grcan_hw_stop(struct grcan_priv *pDev)
0399 {
0400     FUNCDBG();
0401 
0402     /* Mask all IRQs */
0403     pDev->regs->imr = 0;
0404     IRQ_MASK(pDev->irq + GRCAN_IRQ_TXSYNC);
0405     IRQ_MASK(pDev->irq + GRCAN_IRQ_RXSYNC);
0406     IRQ_MASK(pDev->irq + GRCAN_IRQ_IRQ);
0407 
0408     /* Disable receiver & transmitter */
0409     pDev->regs->rx0ctrl = 0;
0410     pDev->regs->tx0ctrl = 0;
0411 }
0412 
0413 static void grcan_sw_stop(struct grcan_priv *pDev)
0414 {
0415     /*
0416      * Release semaphores to wake all threads waiting for an IRQ.
0417      * The threads that
0418      * get woken up must check started state in
0419      * order to determine that they should return to
0420      * user space with error status.
0421      *
0422      * Entering into started mode again will reset the
0423      * semaphore count.
0424      */
0425     rtems_semaphore_release(pDev->rx_sem);
0426     rtems_semaphore_release(pDev->tx_sem);
0427     rtems_semaphore_release(pDev->txempty_sem);
0428 }
0429 
0430 static void grcan_hw_config(struct grcan_priv *pDev, struct grcan_config *conf)
0431 {
0432     unsigned int config = 0;
0433     struct grcan_regs *regs = pDev->regs;
0434 
0435     /* Reset HurriCANe Core */
0436     regs->ctrl = 0;
0437 
0438     if (conf->silent)
0439         config |= GRCAN_CFG_SILENT;
0440 
0441     if (conf->abort)
0442         config |= GRCAN_CFG_ABORT;
0443 
0444     if (conf->selection.selection)
0445         config |= GRCAN_CFG_SELECTION;
0446 
0447     if (conf->selection.enable0)
0448         config |= GRCAN_CFG_ENABLE0;
0449 
0450     if (conf->selection.enable1)
0451         config |= GRCAN_CFG_ENABLE1;
0452 
0453     /* Timing */
0454     if (!pDev->fd_capable) {
0455         config |= (conf->timing.bpr << GRCAN_CFG_BPR_BIT) &
0456               GRCAN_CFG_BPR;
0457         config |= (conf->timing.rsj << GRCAN_CFG_RSJ_BIT) &
0458               GRCAN_CFG_RSJ;
0459         config |= (conf->timing.ps1 << GRCAN_CFG_PS1_BIT) &
0460               GRCAN_CFG_PS1;
0461         config |= (conf->timing.ps2 << GRCAN_CFG_PS2_BIT) &
0462               GRCAN_CFG_PS2;
0463         config |= (conf->timing.scaler << GRCAN_CFG_SCALER_BIT) &
0464                   GRCAN_CFG_SCALER;
0465     } else {
0466         regs->nbtr =
0467             (conf->timing.scaler << GRCANFD_NBTR_SCALER_BIT) |
0468             (conf->timing.ps1 << GRCANFD_NBTR_PS1_BIT) |
0469             (conf->timing.ps2 << GRCANFD_NBTR_PS2_BIT) |
0470             (conf->timing.rsj << GRCANFD_NBTR_SJW_BIT);
0471         regs->fdbtr =
0472             (conf->timing_fd.scaler << GRCANFD_FDBTR_SCALER_BIT) |
0473             (conf->timing_fd.ps1 << GRCANFD_FDBTR_PS1_BIT) |
0474             (conf->timing_fd.ps2 << GRCANFD_FDBTR_PS2_BIT) |
0475             (conf->timing_fd.sjw << GRCANFD_FDBTR_SJW_BIT);
0476     }
0477     /* Write configuration */
0478     regs->conf = config;
0479 
0480     /* Enable HurriCANe Core */
0481     regs->ctrl = GRCAN_CTRL_ENABLE;
0482 }
0483 
0484 static void grcan_hw_accept(
0485     struct grcan_regs *regs,
0486     struct grcan_filter *afilter
0487 )
0488 {
0489     /* Disable Sync mask totaly (if we change scode or smask
0490      * in an unfortunate way we may trigger a sync match)
0491      */
0492     regs->rx0mask = 0xffffffff;
0493 
0494     /* Set Sync Filter in a controlled way */
0495     regs->rx0code = afilter->code;
0496     regs->rx0mask = afilter->mask;
0497 }
0498 
0499 static void grcan_hw_sync(struct grcan_regs *regs, struct grcan_filter *sfilter)
0500 {
0501     /* Disable Sync mask totaly (if we change scode or smask
0502      * in an unfortunate way we may trigger a sync match)
0503      */
0504     regs->smask = 0xffffffff;
0505 
0506     /* Set Sync Filter in a controlled way */
0507     regs->scode = sfilter->code;
0508     regs->smask = sfilter->mask;
0509 }
0510 
0511 int grcan_wait_rxdata(struct grcan_priv *pDev, int min)
0512 {
0513     unsigned int wp, rp, size, irq;
0514     unsigned int irq_trunk, dataavail;
0515     int wait, state;
0516     SPIN_IRQFLAGS(oldLevel);
0517 
0518     FUNCDBG();
0519 
0520     /*** block until receive IRQ received
0521      * Set up a valid IRQ point so that an IRQ is received
0522      * when one or more messages are received
0523      */
0524     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0525     state = pDev->started;
0526 
0527     /* A bus off interrupt may have occured after checking pDev->started */
0528     if (state != STATE_STARTED) {
0529         SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0530         if (state == STATE_BUSOFF) {
0531             DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0532         } else if (state == STATE_AHBERR) {
0533             DBGC(DBG_STATE, "cancelled due to a AHB error\n");
0534         } else {
0535             DBGC(DBG_STATE, "cancelled due to STOP (unexpected) \n");
0536         }
0537         return state2err[state];
0538     }
0539 
0540     size = READ_REG(&pDev->regs->rx0size);
0541     rp = READ_REG(&pDev->regs->rx0rd);
0542     wp = READ_REG(&pDev->regs->rx0wr);
0543 
0544     /**** Calculate IRQ Pointer ****/
0545     irq = wp + min * GRCAN_MSG_SIZE;
0546     /* wrap irq around */
0547     if (irq >= size) {
0548         irq_trunk = irq - size;
0549     } else
0550         irq_trunk = irq;
0551 
0552     /* init IRQ HW */
0553     pDev->regs->rx0irq = irq_trunk;
0554 
0555     /* Clear pending Rx IRQ */
0556     pDev->regs->picr = GRCAN_RXIRQ_IRQ;
0557 
0558     wp = READ_REG(&pDev->regs->rx0wr);
0559 
0560     /* Calculate messages available */
0561     dataavail = grcan_hw_rxavail(rp, wp, size);
0562 
0563     if (dataavail < min) {
0564         /* Still empty, proceed with sleep - Turn on IRQ (unmask irq) */
0565         pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_RXIRQ_IRQ;
0566         wait = 1;
0567     } else {
0568         /* enough message has been received, abort sleep - don't unmask interrupt */
0569         wait = 0;
0570     }
0571     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0572 
0573     /* Wait for IRQ to fire only if has been triggered */
0574     if (wait) {
0575         rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0576         /*
0577          * The semaphore is released either due to the expected IRQ
0578          * condition or by BUSOFF, AHBERROR or another thread calling
0579          * grcan_stop(). In either case, state2err[] has the correnct
0580          * return value.
0581          */
0582         return state2err[pDev->started];
0583     }
0584 
0585     return 0;
0586 }
0587 
0588 /* Wait for TX circular buffer to have room for min CAN messagges. TXIRQ is used to pin
0589  * point the location of the CAN message corresponding to min.
0590  *
0591  * min must be at least WRAP_AROUND_TX_MSGS less than max buffer capacity
0592  * (pDev->txbuf_size/GRCAN_MSG_SIZE) for this algo to work.
0593  */
0594 int grcan_wait_txspace(struct grcan_priv *pDev, int min)
0595 {
0596     int wait, state;
0597     unsigned int irq, rp, wp, size, space_left;
0598     unsigned int irq_trunk;
0599     SPIN_IRQFLAGS(oldLevel);
0600 
0601     DBGC(DBG_TX, "\n");
0602     /*FUNCDBG(); */
0603 
0604     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0605     state = pDev->started;
0606     /* A bus off interrupt may have occured after checking pDev->started */
0607     if (state != STATE_STARTED) {
0608         SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0609         if (state == STATE_BUSOFF) {
0610             DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0611         } else if (state == STATE_AHBERR) {
0612             DBGC(DBG_STATE, "cancelled due to a AHB error\n");
0613         } else {
0614             DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n");
0615         }
0616         return state2err[state];
0617     }
0618 
0619     pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
0620 
0621     size = READ_REG(&pDev->regs->tx0size);
0622     wp = READ_REG(&pDev->regs->tx0wr);
0623 
0624     rp = READ_REG(&pDev->regs->tx0rd);
0625 
0626     /**** Calculate IRQ Pointer ****/
0627     irq = rp + min * GRCAN_MSG_SIZE;
0628     /* wrap irq around */
0629     if (irq >= size) {
0630         irq_trunk = irq - size;
0631     } else
0632         irq_trunk = irq;
0633 
0634     /* trigger HW to do a IRQ when enough room in buffer */
0635     pDev->regs->tx0irq = irq_trunk;
0636 
0637     /* Clear pending Tx IRQ */
0638     pDev->regs->picr = GRCAN_TXIRQ_IRQ;
0639 
0640     /* One problem, if HW already gone past IRQ place the IRQ will
0641      * never be received resulting in a thread hang. We check if so
0642      * before proceeding.
0643      *
0644      * has the HW already gone past the IRQ generation place?
0645      *  == does min fit info tx buffer?
0646      */
0647     rp = READ_REG(&pDev->regs->tx0rd);
0648 
0649     space_left = grcan_hw_txspace(rp, wp, size);
0650 
0651     if (space_left < min) {
0652         /* Still too full, proceed with sleep - Turn on IRQ (unmask irq) */
0653         pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXIRQ_IRQ;
0654         wait = 1;
0655     } else {
0656         /* There are enough room in buffer, abort wait - don't unmask interrupt */
0657         wait = 0;
0658     }
0659     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0660 
0661     /* Wait for IRQ to fire only if it has been triggered */
0662     if (wait) {
0663         rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0664         return state2err[pDev->started];
0665     }
0666 
0667     /* At this point the TxIRQ has been masked, we need not to mask it */
0668     return 0;
0669 }
0670 
0671 static int grcan_tx_flush(struct grcan_priv *pDev)
0672 {
0673     int wait, state;
0674     unsigned int rp, wp;
0675     SPIN_IRQFLAGS(oldLevel);
0676     FUNCDBG();
0677 
0678     /* loop until all data in circular buffer has been read by hw.
0679      * (write pointer != read pointer )
0680      *
0681      * Hardware doesn't update write pointer - we do
0682      */
0683     while (
0684         (wp = READ_REG(&pDev->regs->tx0wr)) !=
0685         (rp = READ_REG(&pDev->regs->tx0rd))
0686     ) {
0687         /* Wait for TX empty IRQ */
0688         SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0689         state = pDev->started;
0690 
0691         /* A bus off interrupt may have occured after checking pDev->started */
0692         if (state != STATE_STARTED) {
0693             SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0694             if (state == STATE_BUSOFF) {
0695                 DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0696             } else if (state == STATE_AHBERR) {
0697                 DBGC(DBG_STATE, "cancelled due to a AHB error\n");
0698             } else {
0699                 DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n");
0700             }
0701             return state2err[state];
0702         }
0703 
0704         /* Clear pending TXEmpty IRQ */
0705         pDev->regs->picr = GRCAN_TXEMPTY_IRQ;
0706 
0707         if (wp != READ_REG(&pDev->regs->tx0rd)) {
0708             /* Still not empty, proceed with sleep - Turn on IRQ (unmask irq) */
0709             pDev->regs->imr =
0710                 READ_REG(&pDev->regs->imr) | GRCAN_TXEMPTY_IRQ;
0711             wait = 1;
0712         } else {
0713             /* TX fifo is empty */
0714             wait = 0;
0715         }
0716         SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0717         if (!wait)
0718             break;
0719 
0720         /* Wait for IRQ to wake us */
0721         rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0722         state = pDev->started;
0723         if (state != STATE_STARTED) {
0724             return state2err[state];
0725         }
0726     }
0727     return 0;
0728 }
0729 
0730 static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx)
0731 {
0732     unsigned int adr;
0733     FUNCDBG();
0734 
0735     if ( tx ) {
0736         adr = (unsigned int)pDev->txbuf_adr;
0737         if (adr & 0x1) {
0738             /* User defined "remote" address. Translate it into
0739              * a CPU accessible address
0740              */
0741             pDev->_tx_hw = (void *)(adr & ~0x1);
0742             drvmgr_translate_check(
0743                 pDev->dev,
0744                 DMAMEM_TO_CPU,
0745                 (void *)pDev->_tx_hw,
0746                 (void **)&pDev->_tx,
0747                 pDev->txbuf_size);
0748             pDev->tx = (struct grcan_msg *)pDev->_tx;
0749         } else {
0750             if (adr == 0) {
0751                 pDev->_tx = grlib_malloc(pDev->txbuf_size +
0752                                    BUFFER_ALIGNMENT_NEEDS);
0753                 if (!pDev->_tx)
0754                     return -1;
0755             } else {
0756                 /* User defined "cou-local" address. Translate
0757                  * it into a CPU accessible address
0758                  */
0759                 pDev->_tx = (void *)adr;
0760             }
0761             /* Align TX buffer */
0762             pDev->tx = (struct grcan_msg *)
0763                        (((unsigned int)pDev->_tx +
0764                    (BUFFER_ALIGNMENT_NEEDS-1)) &
0765                        ~(BUFFER_ALIGNMENT_NEEDS-1));
0766 
0767             /* Translate address into an hardware accessible
0768              * address
0769              */
0770             drvmgr_translate_check(
0771                 pDev->dev,
0772                 CPUMEM_TO_DMA,
0773                 (void *)pDev->tx,
0774                 (void **)&pDev->_tx_hw,
0775                 pDev->txbuf_size);
0776         }
0777     }
0778 
0779     if ( rx ) {
0780         adr = (unsigned int)pDev->rxbuf_adr;
0781         if (adr & 0x1) {
0782             /* User defined "remote" address. Translate it into
0783              * a CPU accessible address
0784              */
0785             pDev->_rx_hw = (void *)(adr & ~0x1);
0786             drvmgr_translate_check(
0787                 pDev->dev,
0788                 DMAMEM_TO_CPU,
0789                 (void *)pDev->_rx_hw,
0790                 (void **)&pDev->_rx,
0791                 pDev->rxbuf_size);
0792             pDev->rx = (struct grcan_msg *)pDev->_rx;
0793         } else {
0794             if (adr == 0) {
0795                 pDev->_rx = grlib_malloc(pDev->rxbuf_size +
0796                                    BUFFER_ALIGNMENT_NEEDS);
0797                 if (!pDev->_rx)
0798                     return -1;
0799             } else {
0800                 /* User defined "cou-local" address. Translate
0801                  * it into a CPU accessible address
0802                  */
0803                 pDev->_rx = (void *)adr;
0804             }
0805             /* Align RX buffer */
0806             pDev->rx = (struct grcan_msg *)
0807                        (((unsigned int)pDev->_rx +
0808                    (BUFFER_ALIGNMENT_NEEDS-1)) &
0809                        ~(BUFFER_ALIGNMENT_NEEDS-1));
0810 
0811             /* Translate address into an hardware accessible
0812              * address
0813              */
0814             drvmgr_translate_check(
0815                 pDev->dev,
0816                 CPUMEM_TO_DMA,
0817                 (void *)pDev->rx,
0818                 (void **)&pDev->_rx_hw,
0819                 pDev->rxbuf_size);
0820         }
0821     }
0822     return 0;
0823 }
0824 
0825 static void grcan_free_buffers(struct grcan_priv *pDev, int rx, int tx)
0826 {
0827     FUNCDBG();
0828 
0829     if (tx && pDev->_tx) {
0830         free(pDev->_tx);
0831         pDev->_tx = NULL;
0832         pDev->tx = NULL;
0833     }
0834 
0835     if (rx && pDev->_rx) {
0836         free(pDev->_rx);
0837         pDev->_rx = NULL;
0838         pDev->rx = NULL;
0839     }
0840 }
0841 
0842 int grcan_dev_count(void)
0843 {
0844     return grcan_count;
0845 }
0846 
0847 void *grcan_open_by_name(char *name, int *dev_no)
0848 {
0849     int i;
0850     for (i = 0; i < grcan_count; i++){
0851         struct grcan_priv *pDev;
0852 
0853         pDev = priv_tab[i];
0854         if (NULL == pDev) {
0855             continue;
0856         }
0857         if (strncmp(pDev->devName, name, NELEM(pDev->devName)) == 0) {
0858             if (dev_no)
0859                 *dev_no = i;
0860             return grcan_open(i);
0861         }
0862     }
0863     return NULL;
0864 }
0865 
0866 void *grcan_open(int dev_no)
0867 {
0868     struct grcan_priv *pDev;
0869     void *ret;
0870     union drvmgr_key_value *value;
0871     struct grlib_canbtrs_ranges *br;
0872 
0873     FUNCDBG();
0874 
0875     if (grcan_count == 0 || (grcan_count <= dev_no)) {
0876         return NULL;
0877     }
0878 
0879     pDev = priv_tab[dev_no];
0880 
0881     /* Wait until we get semaphore */
0882     if (rtems_semaphore_obtain(pDev->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0883         != RTEMS_SUCCESSFUL) {
0884         return NULL;
0885     }
0886 
0887     /* is device busy/taken? */
0888     if ( pDev->open ) {
0889         ret = NULL;
0890         goto out;
0891     }
0892 
0893     SPIN_INIT(&pDev->devlock, pDev->devName);
0894 
0895     /* Mark device taken */
0896     pDev->open = 1;
0897 
0898     pDev->txblock = pDev->rxblock = 1;
0899     pDev->txcomplete = pDev->rxcomplete = 0;
0900     pDev->started = STATE_STOPPED;
0901     pDev->config_changed = 1;
0902     pDev->config.silent = 0;
0903     pDev->config.abort = 0;
0904     pDev->config.selection.selection = 0;
0905     pDev->config.selection.enable0 = 0;
0906     pDev->config.selection.enable1 = 1;
0907     pDev->flushing = 0;
0908     pDev->rx = pDev->_rx = NULL;
0909     pDev->tx = pDev->_tx = NULL;
0910     pDev->txbuf_adr = 0;
0911     pDev->rxbuf_adr = 0;
0912     pDev->txbuf_size = TX_BUF_SIZE;
0913     pDev->rxbuf_size = RX_BUF_SIZE;
0914 
0915     /* Override default buffer sizes if available from bus resource */
0916     value = drvmgr_dev_key_get(pDev->dev, "txBufSize", DRVMGR_KT_INT);
0917     if ( value )
0918         pDev->txbuf_size = value->i;
0919 
0920     value = drvmgr_dev_key_get(pDev->dev, "rxBufSize", DRVMGR_KT_INT);
0921     if ( value )
0922         pDev->rxbuf_size = value->i;
0923 
0924     value = drvmgr_dev_key_get(pDev->dev, "txBufAdr", DRVMGR_KT_POINTER);
0925     if ( value )
0926         pDev->txbuf_adr = value->ptr;
0927 
0928     value = drvmgr_dev_key_get(pDev->dev, "rxBufAdr", DRVMGR_KT_POINTER);
0929     if ( value )
0930         pDev->rxbuf_adr = value->ptr;
0931 
0932     DBG("Defaulting to rxbufsize: %d, txbufsize: %d\n",RX_BUF_SIZE,TX_BUF_SIZE);
0933 
0934     /* Default to accept all messages */
0935     pDev->afilter.mask = 0x00000000;
0936     pDev->afilter.code = 0x00000000;
0937 
0938     /* Default to disable sync messages (only trigger when id is set to all ones) */
0939     pDev->sfilter.mask = 0xffffffff;
0940     pDev->sfilter.code = 0x00000000;
0941 
0942     /* Calculate default timing register values */
0943     if (pDev->fd_capable)
0944         br = &grcanfd_nom_btrs_ranges;
0945     else
0946         br = &grcan_btrs_ranges;
0947     grlib_canbtrs_calc_timing(
0948         GRCAN_DEFAULT_BAUD, pDev->corefreq_hz, GRCAN_SAMPLING_POINT,
0949         br, (struct grlib_canbtrs_timing *)&pDev->config.timing);
0950 
0951     if ( grcan_alloc_buffers(pDev,1,1) ) {
0952         ret = NULL;
0953         goto out;
0954     }
0955 
0956     /* Clear statistics */
0957     memset(&pDev->stats,0,sizeof(struct grcan_stats));
0958 
0959     ret = pDev;
0960 out:
0961     rtems_semaphore_release(pDev->dev_sem);
0962     return ret;
0963 }
0964 
0965 int grcan_close(void *d)
0966 {
0967     struct grcan_priv *pDev = d;
0968 
0969     FUNCDBG();
0970 
0971     grcan_stop(d);
0972 
0973     grcan_hw_reset(pDev->regs);
0974 
0975     grcan_free_buffers(pDev,1,1);
0976 
0977     /* Mark Device as closed */
0978     pDev->open = 0;
0979 
0980     return 0;
0981 }
0982 
0983 int grcan_canfd_capable(void *d)
0984 {
0985     struct grcan_priv *pDev = d;
0986 
0987     return pDev->fd_capable;
0988 }
0989 
0990 int grcan_start(void *d)
0991 {
0992     struct grcan_priv *pDev = d;
0993 
0994     FUNCDBG();
0995 
0996     if (grcan_get_state(d) == STATE_STARTED) {
0997         return -1;
0998     }
0999 
1000     if ( (grcan_hw_start(pDev)) != RTEMS_SUCCESSFUL ){
1001         return -2;
1002     }
1003 
1004     /* Clear semaphore state. This is to avoid effects from previous
1005      * bus-off/stop where semahpores where flushed() but the count remained.
1006      */
1007     rtems_semaphore_obtain(pDev->rx_sem, RTEMS_NO_WAIT, 0);
1008     rtems_semaphore_obtain(pDev->tx_sem, RTEMS_NO_WAIT, 0);
1009     rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_NO_WAIT, 0);
1010 
1011     /* Read and write are now open... */
1012     pDev->started = STATE_STARTED;
1013     DBGC(DBG_STATE, "STOPPED|BUSOFF|AHBERR->STARTED\n");
1014 
1015     /* Register interrupt routine and enable IRQ at IRQ ctrl */
1016     drvmgr_interrupt_register(pDev->dev, 0, pDev->devName,
1017                     grcan_interrupt, pDev);
1018 
1019     return 0;
1020 }
1021 
1022 int grcan_stop(void *d)
1023 {
1024     struct grcan_priv *pDev = d;
1025     SPIN_IRQFLAGS(oldLevel);
1026     int do_sw_stop;
1027 
1028     FUNCDBG();
1029 
1030     if (pDev->started == STATE_STOPPED)
1031         return -1;
1032 
1033     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1034     if (pDev->started == STATE_STARTED) {
1035         grcan_hw_stop(pDev);
1036         do_sw_stop = 1;
1037         DBGC(DBG_STATE, "STARTED->STOPPED\n");
1038     } else {
1039         /*
1040          * started == STATE_[STOPPED|BUSOFF|AHBERR] so grcan_hw_stop()
1041          * might already been called from ISR.
1042          */
1043         DBGC(DBG_STATE, "[STOPPED|BUSOFF|AHBERR]->STOPPED\n");
1044         do_sw_stop = 0;
1045     }
1046     pDev->started = STATE_STOPPED;
1047     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1048 
1049     if (do_sw_stop)
1050         grcan_sw_stop(pDev);
1051 
1052     /* Disable interrupts */
1053     drvmgr_interrupt_unregister(pDev->dev, 0, grcan_interrupt, pDev);
1054 
1055     return 0;
1056 }
1057 
1058 int grcan_get_state(void *d)
1059 {
1060     struct grcan_priv *pDev = d;
1061 
1062     FUNCDBG();
1063 
1064     return pDev->started;
1065 }
1066 
1067 int grcan_flush(void *d)
1068 {
1069     struct grcan_priv *pDev = d;
1070     int tmp;
1071 
1072     FUNCDBG();
1073 
1074     if ((pDev->started != STATE_STARTED) || pDev->flushing || pDev->config.silent)
1075         return -1;
1076 
1077     pDev->flushing = 1;
1078     tmp = grcan_tx_flush(pDev);
1079     pDev->flushing = 0;
1080     if ( tmp ) {
1081         /* The wait has been aborted, probably due to
1082          * the device driver has been closed by another
1083          * thread.
1084          */
1085         return -1;
1086     }
1087 
1088     return 0;
1089 }
1090 
1091 int grcan_set_silent(void* d, int silent)
1092 {
1093     struct grcan_priv *pDev = d;
1094 
1095     FUNCDBG();
1096 
1097     if (pDev->started == STATE_STARTED)
1098         return -1;
1099 
1100     pDev->config.silent = silent;
1101     pDev->config_changed = 1;
1102 
1103     return 0;
1104 }
1105 
1106 int grcan_set_abort(void* d, int abort)
1107 {
1108     struct grcan_priv *pDev = d;
1109 
1110     FUNCDBG();
1111 
1112     if (pDev->started == STATE_STARTED)
1113         return -1;
1114 
1115     pDev->config.abort = abort;
1116     /* This Configuration parameter doesn't need HurriCANe reset
1117      * ==> no pDev->config_changed = 1;
1118      */
1119 
1120     return 0;
1121 }
1122 
1123 int grcan_set_selection(void *d, const struct grcan_selection *selection)
1124 {
1125     struct grcan_priv *pDev = d;
1126 
1127     FUNCDBG();
1128 
1129     if (pDev->started == STATE_STARTED)
1130         return -1;
1131 
1132     if ( !selection )
1133         return -2;
1134 
1135     pDev->config.selection = *selection;
1136     pDev->config_changed = 1;
1137 
1138     return 0;
1139 }
1140 
1141 int grcan_set_rxblock(void *d, int block)
1142 {
1143     struct grcan_priv *pDev = d;
1144 
1145     FUNCDBG();
1146 
1147     pDev->rxblock = block;
1148 
1149     return 0;
1150 }
1151 
1152 int grcan_set_txblock(void *d, int block)
1153 {
1154     struct grcan_priv *pDev = d;
1155 
1156     FUNCDBG();
1157 
1158     pDev->txblock = block;
1159 
1160     return 0;
1161 }
1162 
1163 int grcan_set_txcomplete(void *d, int complete)
1164 {
1165     struct grcan_priv *pDev = d;
1166 
1167     FUNCDBG();
1168 
1169     pDev->txcomplete = complete;
1170 
1171     return 0;
1172 }
1173 
1174 int grcan_set_rxcomplete(void *d, int complete)
1175 {
1176     struct grcan_priv *pDev = d;
1177 
1178     FUNCDBG();
1179 
1180     pDev->rxcomplete = complete;
1181 
1182     return 0;
1183 }
1184 
1185 int grcan_get_stats(void *d, struct grcan_stats *stats)
1186 {
1187     struct grcan_priv *pDev = d;
1188     SPIN_IRQFLAGS(oldLevel);
1189 
1190     FUNCDBG();
1191 
1192     if ( !stats )
1193         return -1;
1194 
1195     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1196     *stats = pDev->stats;
1197     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1198 
1199     return 0;
1200 }
1201 
1202 int grcan_clr_stats(void *d)
1203 {
1204     struct grcan_priv *pDev = d;
1205     SPIN_IRQFLAGS(oldLevel);
1206 
1207     FUNCDBG();
1208 
1209     SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1210     memset(&pDev->stats,0,sizeof(struct grcan_stats));
1211     SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1212 
1213     return 0;
1214 }
1215 
1216 int grcan_set_afilter(void *d, const struct grcan_filter *filter)
1217 {
1218     struct grcan_priv *pDev = d;
1219 
1220     FUNCDBG();
1221 
1222     if ( !filter ){
1223         /* Disable filtering - let all messages pass */
1224         pDev->afilter.mask = 0x0;
1225         pDev->afilter.code = 0x0;
1226     }else{
1227         /* Save filter */
1228         pDev->afilter = *filter;
1229     }
1230     /* Set hardware acceptance filter */
1231     grcan_hw_accept(pDev->regs,&pDev->afilter);
1232 
1233     return 0;
1234 }
1235 
1236 int grcan_set_sfilter(void *d, const struct grcan_filter *filter)
1237 {
1238     struct grcan_priv *pDev = d;
1239     SPIN_IRQFLAGS(oldLevel);
1240 
1241     FUNCDBG();
1242 
1243     if ( !filter ){
1244         /* disable TX/RX SYNC filtering */
1245         pDev->sfilter.mask = 0xffffffff;
1246         pDev->sfilter.code = 0;
1247 
1248          /* disable Sync interrupt */
1249         SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1250         pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~(GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
1251         SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1252     }else{
1253         /* Save filter */
1254         pDev->sfilter = *filter;
1255 
1256         /* Enable Sync interrupt */
1257         SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
1258         pDev->regs->imr = READ_REG(&pDev->regs->imr) | (GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
1259         SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
1260     }
1261     /* Set Sync RX/TX filter */
1262     grcan_hw_sync(pDev->regs,&pDev->sfilter);
1263 
1264     return 0;
1265 }
1266 
1267 int grcan_get_status(void* d, unsigned int *data)
1268 {
1269     struct grcan_priv *pDev = d;
1270 
1271     FUNCDBG();
1272 
1273     if ( !data )
1274         return -1;
1275 
1276     /* Read out the statsu register from the GRCAN core */
1277     data[0] = READ_REG(&pDev->regs->stat);
1278 
1279     return 0;
1280 }
1281 
1282 /* Error indicators */
1283 #define GRCAN_IRQ_ERRORS \
1284         (GRCAN_RXAHBERR_IRQ | GRCAN_TXAHBERR_IRQ | GRCAN_OFF_IRQ)
1285 #define GRCAN_STAT_ERRORS (GRCAN_STAT_AHBERR | GRCAN_STAT_OFF)
1286 /* Warning & RX/TX sync indicators */
1287 #define GRCAN_IRQ_WARNS \
1288         (GRCAN_ERR_IRQ | GRCAN_OR_IRQ | GRCAN_TXLOSS_IRQ | \
1289          GRCAN_RXSYNC_IRQ | GRCAN_TXSYNC_IRQ)
1290 #define GRCAN_STAT_WARNS (GRCAN_STAT_OR | GRCAN_STAT_PASS)
1291 
1292 /* Handle the IRQ */
1293 static void grcan_interrupt(void *arg)
1294 {
1295     struct grcan_priv *pDev = arg;
1296     unsigned int status = READ_REG(&pDev->regs->pimsr);
1297     unsigned int canstat = READ_REG(&pDev->regs->stat);
1298     unsigned int imr_clear;
1299     SPIN_ISR_IRQFLAGS(irqflags);
1300 
1301     /* Spurious IRQ call? */
1302     if ( !status && !canstat )
1303         return;
1304 
1305     if (pDev->started != STATE_STARTED) {
1306         DBGC(DBG_STATE, "not STARTED (unexpected interrupt)\n");
1307         pDev->regs->picr = status;
1308         return;
1309     }
1310 
1311     FUNCDBG();
1312 
1313     if ( (status & GRCAN_IRQ_ERRORS) || (canstat & GRCAN_STAT_ERRORS) ) {
1314         /* Bus-off condition interrupt
1315          * The link is brought down by hardware, we wake all threads
1316          * that is blocked in read/write calls and stop futher calls
1317          * to read/write until user has called ioctl(fd,START,0).
1318          */
1319         SPIN_LOCK(&pDev->devlock, irqflags);
1320         DBGC(DBG_STATE, "STARTED->BUSOFF|AHBERR\n");
1321         pDev->stats.ints++;
1322         if ((status & GRCAN_OFF_IRQ) || (canstat & GRCAN_STAT_OFF)) {
1323             /* CAN Bus-off interrupt */
1324             DBGC(DBG_STATE, "BUSOFF: status: 0x%x, canstat: 0x%x\n",
1325                 status, canstat);
1326             pDev->started = STATE_BUSOFF;
1327             pDev->stats.busoff_cnt++;
1328         } else {
1329             /* RX or Tx AHB Error interrupt */
1330             printk("AHBERROR: status: 0x%x, canstat: 0x%x\n",
1331                 status, canstat);
1332             pDev->started = STATE_AHBERR;
1333             pDev->stats.ahberr_cnt++;
1334         }
1335         grcan_hw_stop(pDev); /* this mask all IRQ sources */
1336         pDev->regs->picr = 0x1ffff; /* clear all interrupts */
1337         /*
1338          * Prevent driver from affecting bus. Driver can be started
1339          * again with grcan_start().
1340          */
1341         SPIN_UNLOCK(&pDev->devlock, irqflags);
1342 
1343         /* Release semaphores to wake blocked threads. */
1344         grcan_sw_stop(pDev);
1345 
1346         /*
1347          * NOTE: Another interrupt may be pending now so ISR could be
1348          * executed one more time aftert this (first) return.
1349          */
1350         return;
1351     }
1352 
1353     /* Mask interrupts in one place under spin-lock. */
1354     imr_clear = status & (GRCAN_RXIRQ_IRQ | GRCAN_TXIRQ_IRQ | GRCAN_TXEMPTY_IRQ);
1355 
1356     SPIN_LOCK(&pDev->devlock, irqflags);
1357 
1358     /* Increment number of interrupts counter */
1359     pDev->stats.ints++;
1360     if ((status & GRCAN_IRQ_WARNS) || (canstat & GRCAN_STAT_WARNS)) {
1361 
1362         if ( (status & GRCAN_ERR_IRQ) || (canstat & GRCAN_STAT_PASS) ) {
1363             /* Error-Passive interrupt */
1364             pDev->stats.passive_cnt++;
1365         }
1366 
1367         if ( (status & GRCAN_OR_IRQ) || (canstat & GRCAN_STAT_OR) ) {
1368             /* Over-run during reception interrupt */
1369             pDev->stats.overrun_cnt++;
1370         }
1371 
1372         if ( status & GRCAN_TXLOSS_IRQ ) {
1373             pDev->stats.txloss_cnt++;
1374         }
1375 
1376         if ( status & GRCAN_TXSYNC_IRQ ) {
1377             /* TxSync message transmitted interrupt */
1378             pDev->stats.txsync_cnt++;
1379         }
1380 
1381         if ( status & GRCAN_RXSYNC_IRQ ) {
1382             /* RxSync message received interrupt */
1383             pDev->stats.rxsync_cnt++;
1384         }
1385     }
1386 
1387     if (imr_clear) {
1388         pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~imr_clear;
1389 
1390         SPIN_UNLOCK(&pDev->devlock, irqflags);
1391 
1392         if ( status & GRCAN_RXIRQ_IRQ ) {
1393             /* RX IRQ pointer interrupt */
1394             rtems_semaphore_release(pDev->rx_sem);
1395         }
1396 
1397         if ( status & GRCAN_TXIRQ_IRQ ) {
1398             /* TX IRQ pointer interrupt */
1399             rtems_semaphore_release(pDev->tx_sem);
1400         }
1401 
1402         if (status & GRCAN_TXEMPTY_IRQ ) {
1403             rtems_semaphore_release(pDev->txempty_sem);
1404         }
1405     } else {
1406         SPIN_UNLOCK(&pDev->devlock, irqflags);
1407     }
1408 
1409     /* Clear IRQs */
1410     pDev->regs->picr = status;
1411 }