source: rtems/c/src/lib/libbsp/sparc/shared/can/occan.c @ a8595605

Last change on this file since a8595605 was a8595605, checked in by Martin Aberg <maberg@…>, on Mar 6, 2017 at 12:08:04 PM

leon, occan: Converted disable/enable to SMP locks

This commit updates the OCCAN driver locking mechanism:

  1. Convert interrupt disable/enable to interrupt locks.
  2. Make sure interrupt service routines use proper locking to deal with threads

running in parallel.

  • Property mode set to 100644
File size: 56.8 KB
Line 
1/*  OC_CAN driver
2 *
3 *  COPYRIGHT (c) 2007.
4 *  Cobham Gaisler AB.
5 *
6 *  The license and distribution terms for this file may be
7 *  found in the file LICENSE in this distribution or at
8 *  http://www.rtems.org/license/LICENSE.
9 */
10
11#include <rtems.h>
12#include <rtems/libio.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <bsp.h>
17#include <rtems/bspIo.h> /* printk */
18
19#include <drvmgr/drvmgr.h>
20#include <drvmgr/ambapp_bus.h>
21#include <bsp/occan.h>
22
23/* RTEMS -> ERRNO decoding table
24
25rtems_assoc_t errno_assoc[] = {
26    { "OK",                 RTEMS_SUCCESSFUL,                0 },
27    { "BUSY",               RTEMS_RESOURCE_IN_USE,           EBUSY },
28    { "INVALID NAME",       RTEMS_INVALID_NAME,              EINVAL },
29    { "NOT IMPLEMENTED",    RTEMS_NOT_IMPLEMENTED,           ENOSYS },
30    { "TIMEOUT",            RTEMS_TIMEOUT,                   ETIMEDOUT },
31    { "NO MEMORY",          RTEMS_NO_MEMORY,                 ENOMEM },
32    { "NO DEVICE",          RTEMS_UNSATISFIED,               ENODEV },
33    { "INVALID NUMBER",     RTEMS_INVALID_NUMBER,            EBADF},
34    { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE,     EPERM},
35    { "IO ERROR",           RTEMS_IO_ERROR,                  EIO},
36    { 0, 0, 0 },
37};
38
39*/
40
41/*
42#undef DEBUG
43#undef DEBUG_EXTRA
44#undef DEBUG_PRINT_REGMAP
45*/
46
47/* default to byte regs */
48#ifndef OCCAN_WORD_REGS
49 #define OCCAN_BYTE_REGS
50#else
51 #undef OCCAN_BYTE_REGS
52#endif
53
54/* Enable Fixup code older OCCAN with a TX IRQ-FLAG bug */
55#define OCCAN_TX_IRQ_FLAG_FIXUP 1
56
57#define OCCAN_WORD_REG_OFS 0x80
58#define OCCAN_NCORE_OFS 0x100
59#define DEFAULT_CLKDIV 0x7
60#define DEFAULT_EXTENDED_MODE 1
61#define DEFAULT_RX_FIFO_LEN 64
62#define DEFAULT_TX_FIFO_LEN 64
63
64/* not implemented yet */
65#undef REDUNDANT_CHANNELS
66
67/* Define common debug macros */
68#ifdef DEBUG
69        #define DBG(fmt, vargs...) printk(fmt, ## vargs )
70#else
71        #define DBG(fmt, vargs...)
72#endif
73
74/* Spin locks mapped via rtems_interrupt_lock_* API: */
75#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
76#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
77#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
78#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
79#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
80#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
81#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
82#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
83
84/* fifo interface */
85typedef struct {
86        int cnt;
87        int ovcnt; /* overwrite count */
88        int full; /* 1 = base contain cnt CANMsgs, tail==head */
89        CANMsg *tail, *head;
90        CANMsg *base;
91        char fifoarea[0];
92} occan_fifo;
93
94/* PELICAN */
95
96typedef struct {
97        unsigned char
98                mode,
99                cmd,
100                status,
101                intflags,
102                inten,
103                resv0,
104                bustim0,
105                bustim1,
106                unused0[2],
107                resv1,
108                arbcode,
109                errcode,
110                errwarn,
111                rx_err_cnt,
112                tx_err_cnt,
113                rx_fi_xff; /* this is also acceptance code 0 in reset mode */
114                union{
115                        struct {
116                                unsigned char id[2];
117                                unsigned char data[8];
118                                unsigned char next_in_fifo[2];
119                        } rx_sff;
120                        struct {
121                                unsigned char id[4];
122                                unsigned char data[8];
123                        } rx_eff;
124                        struct {
125                                unsigned char id[2];
126                                unsigned char data[8];
127                                unsigned char unused[2];
128                        } tx_sff;
129                        struct {
130                                unsigned char id[4];
131                                unsigned char data[8];
132                        } tx_eff;
133                        struct {
134                                unsigned char code[3];
135                                unsigned char mask[4];
136                        } rst_accept;
137                } msg;
138                unsigned char rx_msg_cnt;
139                unsigned char unused1;
140                unsigned char clkdiv;
141} pelican8_regs;
142
143typedef struct {
144        unsigned char
145                mode, unused0[3],
146                cmd, unused1[3],
147                status, unused2[3],
148                intflags, unused3[3],
149                inten, unused4[3],
150                resv0, unused5[3],
151                bustim0, unused6[3],
152                bustim1, unused7[3],
153                unused8[8],
154                resv1,unused9[3],
155                arbcode,unused10[3],
156                errcode,unused11[3],
157                errwarn,unused12[3],
158                rx_err_cnt,unused13[3],
159                tx_err_cnt,unused14[3],
160                rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */
161                /* make sure to use pointers when writing (byte access) to these registers */
162                union{
163                        struct {
164                                unsigned int id[2];
165                                unsigned int data[8];
166                                unsigned int next_in_fifo[2];
167                        } rx_sff;
168                        struct {
169                                unsigned int id[4];
170                                unsigned int data[8];
171                        } rx_eff;
172                        struct {
173                                unsigned int id[2];
174                                unsigned int data[8];
175                        } tx_sff;
176                        struct {
177                                unsigned int id[4];
178                                unsigned int data[8];
179                        } tx_eff;
180                        struct {
181                                unsigned int code[3];
182                                unsigned int mask[4];
183                        } rst_accept;
184                } msg;
185                unsigned char rx_msg_cnt,unused16[3];
186                unsigned char unused17[4];
187                unsigned char clkdiv,unused18[3];
188} pelican32_regs;
189
190#ifdef OCCAN_BYTE_REGS
191#define pelican_regs pelican8_regs
192#else
193#define pelican_regs pelican32_regs
194#endif
195
196
197#define MAX_TSEG2 7
198#define MAX_TSEG1 15
199
200#if 0
201typedef struct {
202        unsigned char brp;
203        unsigned char sjw;
204        unsigned char tseg1;
205        unsigned char tseg2;
206        unsigned char sam;
207} occan_speed_regs;
208#endif
209typedef struct {
210        unsigned char btr0;
211        unsigned char btr1;
212} occan_speed_regs;
213
214typedef struct {
215        struct drvmgr_dev *dev;
216        char devName[32];
217        SPIN_DECLARE(devlock);
218
219        /* hardware shortcuts */
220        pelican_regs *regs;
221        int byte_regs;
222        int irq;
223        occan_speed_regs timing;
224        int channel; /* 0=default, 1=second bus */
225        int single_mode;
226        unsigned int sys_freq_hz;
227
228        /* driver state */
229        rtems_id devsem;
230        rtems_id txsem;
231        rtems_id rxsem;
232        int open;
233        int started;
234        int rxblk;
235        int txblk;
236        int sending;
237        unsigned int status;
238        occan_stats stats;
239
240        /* rx&tx fifos */
241        occan_fifo *rxfifo;
242        occan_fifo *txfifo;
243
244        /* Config */
245        unsigned int speed; /* speed in HZ */
246        unsigned char acode[4];
247        unsigned char amask[4];
248} occan_priv;
249
250/********** FIFO INTERFACE **********/
251static void occan_fifo_put(occan_fifo *fifo);
252static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force);
253static occan_fifo *occan_fifo_create(int cnt);
254static void occan_fifo_free(occan_fifo *fifo);
255static int occan_fifo_full(occan_fifo *fifo);
256static int occan_fifo_empty(occan_fifo *fifo);
257static void occan_fifo_get(occan_fifo *fifo);
258static CANMsg *occan_fifo_claim_get(occan_fifo *fifo);
259static void occan_fifo_clr(occan_fifo *fifo);
260
261/**** Hardware related Interface ****/
262static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result);
263static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing);
264static int pelican_speed_auto(occan_priv *priv);
265static void pelican_init(occan_priv *priv);
266static void pelican_open(occan_priv *priv);
267static int pelican_start(occan_priv *priv);
268static void pelican_stop(occan_priv *priv);
269static int pelican_send(occan_priv *can, CANMsg *msg);
270static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask);
271void occan_interrupt(void *arg);
272#ifdef DEBUG_PRINT_REGMAP
273static void pelican_regadr_print(pelican_regs *regs);
274#endif
275
276/***** Driver related interface *****/
277static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
278static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
279static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
280static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
281static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
282static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg);
283
284#define OCCAN_DRIVER_TABLE_ENTRY { occan_initialize, occan_open, occan_close, occan_read, occan_write, occan_ioctl }
285static rtems_driver_address_table occan_driver = OCCAN_DRIVER_TABLE_ENTRY;
286
287
288/* Read byte bypassing */
289
290
291/* Bypass cache */
292#define READ_REG(priv, address) occan_reg_read(priv, (unsigned int)address)
293#define WRITE_REG(priv, address, data) occan_reg_write(priv, (unsigned int)address, data)
294
295static unsigned int occan_reg_read(occan_priv *priv, unsigned int address)
296{
297        unsigned int adr;
298        if ( priv->byte_regs ) {
299                adr = address;
300        } else {
301                /* Word accessed registers */
302                adr = (address & (~0x7f)) | ((address & 0x7f)<<2);
303        }
304        return *(volatile unsigned char *)adr;
305}
306
307static void occan_reg_write(
308        occan_priv *priv, 
309        unsigned int address,
310        unsigned char value)
311{
312        unsigned int adr;
313        if ( priv->byte_regs ) {
314                adr = address;
315        } else {
316                /* Word accessed registers */
317                adr = (address & (~0x7f)) | ((address & 0x7f)<<2);
318        }
319        *(volatile unsigned char *)adr = value;;
320}
321
322/* Mode register bit definitions */
323#define PELICAN_MOD_RESET          0x1
324#define PELICAN_MOD_LISTEN         0x2
325#define PELICAN_MOD_SELFTEST       0x4
326#define PELICAN_MOD_ACCEPT         0x8
327
328/* Command register bit definitions */
329#define PELICAN_CMD_TXREQ          0x1
330#define PELICAN_CMD_ABORT          0x2
331#define PELICAN_CMD_RELRXBUF       0x4
332#define PELICAN_CMD_CLRDOVR        0x8
333#define PELICAN_CMD_SELFRXRQ       0x10
334
335/* Status register bit definitions */
336#define PELICAN_STAT_RXBUF         0x1
337#define PELICAN_STAT_DOVR          0x2
338#define PELICAN_STAT_TXBUF         0x4
339#define PELICAN_STAT_TXOK          0x8
340#define PELICAN_STAT_RX            0x10
341#define PELICAN_STAT_TX            0x20
342#define PELICAN_STAT_ERR           0x40
343#define PELICAN_STAT_BUS           0x80
344
345/* Interrupt register bit definitions */
346#define PELICAN_IF_RX         0x1
347#define PELICAN_IF_TX         0x2
348#define PELICAN_IF_ERRW       0x4
349#define PELICAN_IF_DOVR       0x8
350#define PELICAN_IF_ERRP       0x20
351#define PELICAN_IF_ARB        0x40
352#define PELICAN_IF_BUS        0x80
353
354/* Interrupt Enable register bit definitions */
355#define PELICAN_IE_RX         0x1
356#define PELICAN_IE_TX         0x2
357#define PELICAN_IE_ERRW       0x4
358#define PELICAN_IE_DOVR       0x8
359#define PELICAN_IE_ERRP       0x20
360#define PELICAN_IE_ARB        0x40
361#define PELICAN_IE_BUS        0x80
362
363/* Arbitration lost capture register bit definitions */
364#define PELICAN_ARB_BITS      0x1f
365
366/*  register bit definitions */
367#define PELICAN_ECC_CODE_BIT     0x00
368#define PELICAN_ECC_CODE_FORM    0x40
369#define PELICAN_ECC_CODE_STUFF   0x80
370#define PELICAN_ECC_CODE_OTHER   0xc0
371#define PELICAN_ECC_CODE    0xc0
372
373#define PELICAN_ECC_DIR     0x20
374#define PELICAN_ECC_SEG     0x1f
375
376/* Clock divider register bit definitions */
377#define PELICAN_CDR_DIV  0x7
378#define PELICAN_CDR_OFF  0x8
379#define PELICAN_CDR_MODE 0x80
380#define PELICAN_CDR_MODE_PELICAN 0x80
381#define PELICAN_CDR_MODE_BITS 7
382#define PELICAN_CDR_MODE_BASICAN 0x00
383
384
385/*  register bit definitions */
386#define OCCAN_BUSTIM_SJW       0xc0
387#define OCCAN_BUSTIM_BRP       0x3f
388#define OCCAN_BUSTIM_SJW_BIT   6
389
390#define OCCAN_BUSTIM_SAM       0x80
391#define OCCAN_BUSTIM_TSEG2     0x70
392#define OCCAN_BUSTIM_TSEG2_BIT 4
393#define OCCAN_BUSTIM_TSEG1     0x0f
394
395/*  register bit definitions */
396/*
397#define PELICAN_S_       0x1
398#define PELICAN_S_       0x2
399#define PELICAN_S_       0x4
400#define PELICAN_S_       0x8
401#define PELICAN_S_       0x10
402#define PELICAN_S_       0x20
403#define PELICAN_S_       0x40
404#define PELICAN_S_       0x80
405*/
406
407static int occan_driver_io_registered = 0;
408static rtems_device_major_number occan_driver_io_major = 0;
409
410/******************* Driver manager interface ***********************/
411
412/* Driver prototypes */
413int occan_register_io(rtems_device_major_number *m);
414int occan_device_init(occan_priv *pDev);
415
416int occan_init2(struct drvmgr_dev *dev);
417int occan_init3(struct drvmgr_dev *dev);
418
419struct drvmgr_drv_ops occan_ops = 
420{
421        .init = {NULL, occan_init2, occan_init3, NULL},
422        .remove = NULL,
423        .info = NULL
424};
425
426struct amba_dev_id occan_ids[] = 
427{
428        {VENDOR_GAISLER, GAISLER_CANAHB},
429        {0, 0}          /* Mark end of table */
430};
431
432struct amba_drv_info occan_drv_info =
433{
434        {
435                DRVMGR_OBJ_DRV,                 /* Driver */
436                NULL,                           /* Next driver */
437                NULL,                           /* Device list */
438                DRIVER_AMBAPP_GAISLER_OCCAN_ID, /* Driver ID */
439                "OCCAN_DRV",                    /* Driver Name */
440                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
441                &occan_ops,
442                NULL,                           /* Funcs */
443                0,                              /* No devices yet */
444                0,
445        },
446        &occan_ids[0]
447};
448
449void occan_register_drv (void)
450{
451        DBG("Registering OCCAN driver\n");
452        drvmgr_drv_register(&occan_drv_info.general);
453}
454
455int occan_init2(struct drvmgr_dev *dev)
456{
457        occan_priv *priv;
458
459        DBG("OCCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
460        priv = dev->priv = malloc(sizeof(occan_priv));
461        if ( !priv )
462                return DRVMGR_NOMEM;
463        memset(priv, 0, sizeof(*priv));
464        priv->dev = dev;
465
466        return DRVMGR_OK;
467}
468
469int occan_init3(struct drvmgr_dev *dev)
470{
471        occan_priv *priv;
472        char prefix[32];
473        rtems_status_code status;
474
475        priv = dev->priv;
476
477        /* Do initialization */
478
479        if ( occan_driver_io_registered == 0) {
480                /* Register the I/O driver only once for all cores */
481                if ( occan_register_io(&occan_driver_io_major) ) {
482                        /* Failed to register I/O driver */
483                        dev->priv = NULL;
484                        return DRVMGR_FAIL;
485                }
486
487                occan_driver_io_registered = 1;
488        }
489
490        /* I/O system registered and initialized
491         * Now we take care of device initialization.
492         */
493
494        if ( occan_device_init(priv) ) {
495                return DRVMGR_FAIL;
496        }
497
498        /* Get Filesystem name prefix */
499        prefix[0] = '\0';
500        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
501                /* Failed to get prefix, make sure of a unique FS name
502                 * by using the driver minor.
503                 */
504                sprintf(priv->devName, "/dev/occan%d", dev->minor_drv);
505        } else {
506                /* Got special prefix, this means we have a bus prefix
507                 * And we should use our "bus minor"
508                 */
509                sprintf(priv->devName, "/dev/%soccan%d", prefix, dev->minor_bus);
510        }
511
512        /* Register Device */
513        DBG("OCCAN[%d]: Registering %s\n", dev->minor_drv, priv->devName);
514        status = rtems_io_register_name(priv->devName, occan_driver_io_major, dev->minor_drv);
515        if (status != RTEMS_SUCCESSFUL) {
516                return DRVMGR_FAIL;
517        }
518
519        return DRVMGR_OK;
520}
521
522/******************* Driver Implementation ***********************/
523
524int occan_register_io(rtems_device_major_number *m)
525{
526        rtems_status_code r;
527
528        if ((r = rtems_io_register_driver(0, &occan_driver, m)) == RTEMS_SUCCESSFUL) {
529                DBG("OCCAN driver successfully registered, major: %d\n", *m);
530        } else {
531                switch(r) {
532                case RTEMS_TOO_MANY:
533                        printk("OCCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
534                        return -1;
535                case RTEMS_INVALID_NUMBER: 
536                        printk("OCCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
537                        return -1;
538                case RTEMS_RESOURCE_IN_USE:
539                        printk("OCCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
540                        return -1;
541                default:
542                        printk("OCCAN rtems_io_register_driver failed\n");
543                        return -1;
544                }
545        }
546        return 0;
547}
548
549int occan_device_init(occan_priv *pDev)
550{
551        struct amba_dev_info *ambadev;
552        struct ambapp_core *pnpinfo;
553        rtems_status_code status;
554        int minor;
555
556        /* Get device information from AMBA PnP information */
557        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
558        if ( ambadev == NULL ) {
559                return -1;
560        }
561        pnpinfo = &ambadev->info;
562        pDev->irq = pnpinfo->irq;
563        pDev->regs = (pelican_regs *)(pnpinfo->ahb_slv->start[0] + OCCAN_NCORE_OFS*pnpinfo->index);
564        pDev->byte_regs = 1;
565        minor = pDev->dev->minor_drv;
566
567        /* Get frequency in Hz */
568        if ( drvmgr_freq_get(pDev->dev, DEV_AHB_SLV, &pDev->sys_freq_hz) ) {
569                return -1;
570        }
571
572        DBG("OCCAN frequency: %d Hz\n", pDev->sys_freq_hz);
573
574        /* initialize software */
575        pDev->open = 0;
576        pDev->started = 0; /* Needed for spurious interrupts */
577        pDev->rxfifo = NULL;
578        pDev->txfifo = NULL;
579        status = rtems_semaphore_create(
580                        rtems_build_name('C', 'd', 'v', '0'+minor),
581                        1,
582                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
583                        RTEMS_NO_PRIORITY_CEILING,
584                        0, 
585                        &pDev->devsem);
586        if ( status != RTEMS_SUCCESSFUL ){
587                printk("OCCAN[%d]: Failed to create dev semaphore, (%d)\n\r",minor, status);
588                return RTEMS_UNSATISFIED;
589        }
590        status = rtems_semaphore_create(
591                        rtems_build_name('C', 't', 'x', '0'+minor),
592                        0, 
593                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
594                        RTEMS_NO_PRIORITY_CEILING,
595                        0, 
596                        &pDev->txsem);
597        if ( status != RTEMS_SUCCESSFUL ){
598                printk("OCCAN[%d]: Failed to create tx semaphore, (%d)\n\r",minor, status);
599                return RTEMS_UNSATISFIED;
600        }
601        status = rtems_semaphore_create(
602                        rtems_build_name('C', 'r', 'x', '0'+minor),
603                        0, 
604                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
605                        RTEMS_NO_PRIORITY_CEILING,
606                        0,
607                        &pDev->rxsem);
608        if ( status != RTEMS_SUCCESSFUL ){
609                printk("OCCAN[%d]: Failed to create rx semaphore, (%d)\n\r",minor, status);
610                return RTEMS_UNSATISFIED;
611        }
612
613        /* hardware init/reset */
614        pelican_init(pDev);
615
616#ifdef DEBUG_PRINT_REGMAP
617        pelican_regadr_print(pDev->regs);
618#endif
619
620        return 0;
621}
622
623
624#ifdef DEBUG
625static void pelican_regs_print(occan_priv *pDev){
626        pelican_regs *regs = pDev->regs;
627        printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
628        printk(" MODE: 0x%02x\n\r",READ_REG(pDev, &regs->mode));
629        printk(" CMD: 0x%02x\n\r",READ_REG(pDev, &regs->cmd));
630        printk(" STATUS: 0x%02x\n\r",READ_REG(pDev, &regs->status));
631        /*printk(" INTFLG: 0x%02x\n\r",READ_REG(pDev, &regs->intflags));*/
632        printk(" INTEN: 0x%02x\n\r",READ_REG(pDev, &regs->inten));
633        printk(" BTR0: 0x%02x\n\r",READ_REG(pDev, &regs->bustim0));
634        printk(" BTR1: 0x%02x\n\r",READ_REG(pDev, &regs->bustim1));
635        printk(" ARBCODE: 0x%02x\n\r",READ_REG(pDev, &regs->arbcode));
636        printk(" ERRCODE: 0x%02x\n\r",READ_REG(pDev, &regs->errcode));
637        printk(" ERRWARN: 0x%02x\n\r",READ_REG(pDev, &regs->errwarn));
638        printk(" RX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->rx_err_cnt));
639        printk(" TX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->tx_err_cnt));
640        if ( READ_REG(pDev, &regs->mode) & PELICAN_MOD_RESET ){
641                /* in reset mode it is possible to read acceptance filters */
642                printk(" ACR0: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->rx_fi_xff),&regs->rx_fi_xff);
643                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.code[0]),(unsigned int)&regs->msg.rst_accept.code[0]);
644                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.code[1]),(unsigned int)&regs->msg.rst_accept.code[1]);
645                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.code[2]),(unsigned int)&regs->msg.rst_accept.code[2]);
646                printk(" AMR0: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.mask[0]),(unsigned int)&regs->msg.rst_accept.mask[0]);
647                printk(" AMR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.mask[1]),(unsigned int)&regs->msg.rst_accept.mask[1]);
648                printk(" AMR2: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.mask[2]),(unsigned int)&regs->msg.rst_accept.mask[2]);
649                printk(" AMR3: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->msg.rst_accept.mask[3]),(unsigned int)&regs->msg.rst_accept.mask[3]);
650               
651        }else{
652                printk(" RXFI_XFF: 0x%02x\n\r",READ_REG(pDev, &regs->rx_fi_xff));
653        }
654        printk(" RX_MSG_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->rx_msg_cnt));
655        printk(" CLKDIV: 0x%02x\n\r",READ_REG(pDev, &regs->clkdiv));
656        printk("-------------------\n\r");
657}
658#endif
659
660#ifdef DEBUG_PRINT_REGMAP
661static void pelican_regadr_print(pelican_regs *regs){
662        printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
663        printk(" MODE: 0x%lx\n\r",(unsigned int)&regs->mode);
664        printk(" CMD: 0x%lx\n\r",(unsigned int)&regs->cmd);
665        printk(" STATUS: 0x%lx\n\r",(unsigned int)&regs->status);
666        /*printk(" INTFLG: 0x%lx\n\r",&regs->intflags);*/
667        printk(" INTEN: 0x%lx\n\r",(unsigned int)&regs->inten);
668        printk(" BTR0: 0x%lx\n\r",(unsigned int)&regs->bustim0);
669        printk(" BTR1: 0x%lx\n\r",(unsigned int)&regs->bustim1);
670        printk(" ARBCODE: 0x%lx\n\r",(unsigned int)&regs->arbcode);
671        printk(" ERRCODE: 0x%lx\n\r",(unsigned int)&regs->errcode);
672        printk(" ERRWARN: 0x%lx\n\r",(unsigned int)&regs->errwarn);
673        printk(" RX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_err_cnt);
674        printk(" TX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->tx_err_cnt);
675
676        /* in reset mode it is possible to read acceptance filters */
677        printk(" RXFI_XFF: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
678       
679        /* reset registers */
680        printk(" ACR0: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
681        printk(" ACR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[0]);
682        printk(" ACR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[1]);
683        printk(" ACR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[2]);
684        printk(" AMR0: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[0]);
685        printk(" AMR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[1]);
686        printk(" AMR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[2]);
687        printk(" AMR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[3]);
688       
689        /* TX Extended */
690        printk(" EFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[0]);
691        printk(" EFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[1]);
692        printk(" EFFTX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[2]);
693        printk(" EFFTX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[3]);
694
695        printk(" EFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[0]);
696        printk(" EFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[1]);
697        printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[2]);   
698        printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[3]);   
699        printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[4]);   
700        printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[5]);   
701        printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[6]);   
702        printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[7]);   
703
704        /* RX Extended */
705        printk(" EFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[0]);
706        printk(" EFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[1]);
707        printk(" EFFRX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[2]);
708        printk(" EFFRX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[3]);
709
710        printk(" EFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[0]);
711        printk(" EFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[1]);
712        printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[2]);   
713        printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[3]);   
714        printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[4]);   
715        printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[5]);   
716        printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[6]);   
717        printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[7]);   
718
719
720        /* RX Extended */
721        printk(" SFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[0]);
722        printk(" SFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[1]);
723
724        printk(" SFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[0]);
725        printk(" SFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[1]);
726        printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[2]);   
727        printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[3]);   
728        printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[4]);   
729        printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[5]);   
730        printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[6]);   
731        printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[7]);   
732
733        /* TX Extended */
734        printk(" SFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[0]);
735        printk(" SFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[1]);
736
737        printk(" SFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[0]);
738        printk(" SFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[1]);
739        printk(" SFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[2]);
740        printk(" SFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[3]);
741        printk(" SFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[4]);
742        printk(" SFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[5]);
743        printk(" SFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[6]);
744        printk(" SFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[7]);
745
746        printk(" RX_MSG_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_msg_cnt);
747        printk(" CLKDIV: 0x%lx\n\r",(unsigned int)&regs->clkdiv);
748        printk("-------------------\n\r");
749}
750#endif
751
752#ifdef DEBUG
753static void occan_stat_print(occan_stats *stats){
754        printk("----Stats----\n\r");
755        printk("rx_msgs: %d\n\r",stats->rx_msgs);
756        printk("tx_msgs: %d\n\r",stats->tx_msgs);
757        printk("err_warn: %d\n\r",stats->err_warn);
758        printk("err_dovr: %d\n\r",stats->err_dovr);
759        printk("err_errp: %d\n\r",stats->err_errp);
760        printk("err_arb: %d\n\r",stats->err_arb);
761        printk("err_bus: %d\n\r",stats->err_bus);
762        printk("Int cnt: %d\n\r",stats->ints);
763        printk("tx_buf_err: %d\n\r",stats->tx_buf_error);
764        printk("-------------\n\r");
765}
766#endif
767
768static void pelican_init(occan_priv *priv){
769        /* Reset core */
770        WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET);
771
772        /* wait for core to reset complete */
773        /*usleep(1);*/
774}
775
776static void pelican_open(occan_priv *priv){
777        int ret;
778
779        /* Set defaults */
780        priv->speed = OCCAN_SPEED_250K;
781
782        /* set acceptance filters to accept all messages */
783        priv->acode[0] = 0;
784        priv->acode[1] = 0;
785        priv->acode[2] = 0;
786        priv->acode[3] = 0;
787        priv->amask[0] = 0xff;
788        priv->amask[1] = 0xff;
789        priv->amask[2] = 0xff;
790        priv->amask[3] = 0xff;
791
792        /* Set clock divider to extended mode, clkdiv not connected
793         */
794        WRITE_REG(priv, &priv->regs->clkdiv, (1<<PELICAN_CDR_MODE_BITS) | (DEFAULT_CLKDIV & PELICAN_CDR_DIV));
795
796        ret = occan_calc_speedregs(priv->sys_freq_hz,priv->speed,&priv->timing);
797        if ( ret ){
798                /* failed to set speed for this system freq, try with 50K instead */
799                priv->speed = OCCAN_SPEED_50K;
800                occan_calc_speedregs(priv->sys_freq_hz, priv->speed,
801                        &priv->timing);
802        }
803
804        /* disable all interrupts */
805        WRITE_REG(priv, &priv->regs->inten, 0);
806
807        /* clear pending interrupts by reading */
808        READ_REG(priv, &priv->regs->intflags);
809}
810
811static int pelican_start(occan_priv *priv){
812        /* Start HW communication */
813
814        if ( !priv->rxfifo || !priv->txfifo )
815                return -1;
816
817        /* In case we were started before and stopped we
818         * should empty the TX fifo or try to resend those
819         * messages. We make it simple...
820         */
821        occan_fifo_clr(priv->txfifo);
822
823        /* Clear status bits */
824        priv->status = 0;
825        priv->sending = 0;
826
827        /* clear pending interrupts */
828        READ_REG(priv, &priv->regs->intflags);
829
830        /* clear error counters */
831        WRITE_REG(priv, &priv->regs->rx_err_cnt, 0);
832        WRITE_REG(priv, &priv->regs->tx_err_cnt, 0);
833
834#ifdef REDUNDANT_CHANNELS
835        if ( (priv->channel == 0) || (priv->channel >= REDUNDANT_CHANNELS) ){
836                /* Select the first (default) channel */
837                OCCAN_SET_CHANNEL(priv,0);
838        }else{
839                /* set gpio bit, or something */
840                OCCAN_SET_CHANNEL(priv,priv->channel);
841        }
842#endif
843        /* set the speed regs of the CAN core */
844        occan_set_speedregs(priv,&priv->timing);
845
846        DBG("OCCAN: start: set timing regs btr0: 0x%x, btr1: 0x%x\n\r",
847                READ_REG(priv, &priv->regs->bustim0),
848                READ_REG(priv, &priv->regs->bustim1));
849
850        /* Set default acceptance filter */
851        pelican_set_accept(priv,priv->acode,priv->amask);
852
853        /* Nothing can fail from here, this must be set before interrupts are
854         * enabled */
855        priv->started = 1;
856
857        /* turn on interrupts */
858        WRITE_REG(priv, &priv->regs->inten,
859                PELICAN_IE_RX | PELICAN_IE_TX | PELICAN_IE_ERRW |
860                PELICAN_IE_ERRP | PELICAN_IE_BUS);
861#ifdef DEBUG
862        /* print setup before starting */
863        pelican_regs_print(priv->regs);
864        occan_stat_print(&priv->stats);
865#endif
866
867        /* core already in reset mode,
868         *  € Exit reset mode
869         *  € Enter Single/Dual mode filtering.
870         */
871        WRITE_REG(priv, &priv->regs->mode, (priv->single_mode << 3));
872
873        /* Register interrupt routine and unmask IRQ at IRQ controller */
874        drvmgr_interrupt_register(priv->dev, 0, "occan", occan_interrupt, priv);
875
876        return 0;
877}
878
879static void pelican_stop(occan_priv *priv)
880{
881        /* stop HW */
882
883        drvmgr_interrupt_unregister(priv->dev, 0, occan_interrupt, priv);
884
885#ifdef DEBUG
886        /* print setup before stopping */
887        pelican_regs_print(priv->regs);
888        occan_stat_print(&priv->stats);
889#endif
890
891        /* put core in reset mode */
892        WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET);
893
894        /* turn off interrupts */
895        WRITE_REG(priv, &priv->regs->inten, 0);
896
897        priv->status |= OCCAN_STATUS_RESET;
898}
899
900static inline int pelican_tx_ready(occan_priv *can)
901{
902        unsigned char status;
903        pelican_regs *regs = can->regs;
904
905        /* is there room in send buffer? */
906        status = READ_REG(can, &regs->status);
907        if ( !(status & PELICAN_STAT_TXBUF) ) {
908                /* tx fifo taken, we have to wait */
909                return 0;
910        }
911
912        return 1;
913}
914
915/* Try to send message "msg", if hardware txfifo is
916 * full, then -1 is returned.
917 *
918 * Be sure to have disabled CAN interrupts when
919 * entering this function.
920 */
921static int pelican_send(occan_priv *can, CANMsg *msg){
922        unsigned char tmp;
923        pelican_regs *regs = can->regs;
924
925        /* is there room in send buffer? */
926        if ( !pelican_tx_ready(can) ) {
927                /* tx fifo taken, we have to wait */
928                return -1;
929        }
930
931        tmp = msg->len & 0xf;
932        if ( msg->rtr )
933                tmp |= 0x40;
934
935        if ( msg->extended ){
936                /* Extended Frame */
937                WRITE_REG(can, &regs->rx_fi_xff, 0x80 | tmp);
938                WRITE_REG(can, &regs->msg.tx_eff.id[0],(msg->id >> (5+8+8)) & 0xff);
939                WRITE_REG(can, &regs->msg.tx_eff.id[1],(msg->id >> (5+8)) & 0xff);
940                WRITE_REG(can, &regs->msg.tx_eff.id[2],(msg->id >> (5)) & 0xff);
941                WRITE_REG(can, &regs->msg.tx_eff.id[3],(msg->id << 3) & 0xf8);
942                tmp = msg->len;
943                while(tmp--){
944                        WRITE_REG(can, &regs->msg.tx_eff.data[tmp], msg->data[tmp]);
945                }
946        }else{
947                /* Standard Frame */
948                WRITE_REG(can, &regs->rx_fi_xff, tmp);
949                WRITE_REG(can, &regs->msg.tx_sff.id[0],(msg->id >> 3) & 0xff);
950                WRITE_REG(can, &regs->msg.tx_sff.id[1],(msg->id << 5) & 0xe0);
951                tmp = msg->len;
952                while(tmp--){
953                        WRITE_REG(can, &regs->msg.tx_sff.data[tmp],msg->data[tmp]);
954                }
955        }
956
957        /* let HW know of new message */
958        if ( msg->sshot ){
959                WRITE_REG(can, &regs->cmd, PELICAN_CMD_TXREQ | PELICAN_CMD_ABORT);
960        }else{
961                /* normal case -- try resend until sent */
962                WRITE_REG(can, &regs->cmd, PELICAN_CMD_TXREQ);
963        }
964
965        return 0;
966}
967
968
969static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask)
970{
971        unsigned char *acode0, *acode1, *acode2, *acode3;
972        unsigned char *amask0, *amask1, *amask2, *amask3;
973
974        acode0 = &priv->regs->rx_fi_xff;
975        acode1 = (unsigned char *)&priv->regs->msg.rst_accept.code[0];
976        acode2 = (unsigned char *)&priv->regs->msg.rst_accept.code[1];
977        acode3 = (unsigned char *)&priv->regs->msg.rst_accept.code[2];
978
979        amask0 = (unsigned char *)&priv->regs->msg.rst_accept.mask[0];
980        amask1 = (unsigned char *)&priv->regs->msg.rst_accept.mask[1];
981        amask2 = (unsigned char *)&priv->regs->msg.rst_accept.mask[2];
982        amask3 = (unsigned char *)&priv->regs->msg.rst_accept.mask[3];
983
984        /* Set new mask & code */
985        WRITE_REG(priv, acode0, acode[0]);
986        WRITE_REG(priv, acode1, acode[1]);
987        WRITE_REG(priv, acode2, acode[2]);
988        WRITE_REG(priv, acode3, acode[3]);
989
990        WRITE_REG(priv, amask0, amask[0]);
991        WRITE_REG(priv, amask1, amask[1]);
992        WRITE_REG(priv, amask2, amask[2]);
993        WRITE_REG(priv, amask3, amask[3]);
994}
995
996
997/* This function calculates BTR0 and BTR1 values for a given bitrate.
998 *
999 * Set communication parameters.
1000 * \param clock_hz OC_CAN Core frequency in Hz.
1001 * \param rate Requested baud rate in bits/second.
1002 * \param result Pointer to where resulting BTRs will be stored.
1003 * \return zero if successful to calculate a baud rate.
1004 */
1005static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result)
1006{
1007        int best_error = 1000000000;
1008        int error;
1009        int best_tseg=0, best_brp=0, brp=0;
1010        int tseg=0, tseg1=0, tseg2=0;
1011        int sjw = 0;
1012        int clock = clock_hz / 2;
1013        int sampl_pt = 90;
1014
1015        if ( (rate<5000) || (rate>1000000) ){
1016                /* invalid speed mode */
1017                return -1;
1018        }
1019
1020        /* find best match, return -2 if no good reg
1021         * combination is available for this frequency */
1022
1023        /* some heuristic specials */
1024        if (rate > ((1000000 + 500000) / 2))
1025                sampl_pt = 75;
1026
1027        if (rate < ((12500 + 10000) / 2))
1028                sampl_pt = 75;
1029
1030        if (rate < ((100000 + 125000) / 2))
1031                sjw = 1;
1032
1033        /* tseg even = round down, odd = round up */
1034        for (tseg = (0 + 0 + 2) * 2;
1035             tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1;
1036             tseg++)
1037        {
1038                brp = clock / ((1 + tseg / 2) * rate) + tseg % 2;
1039                if ((brp == 0) || (brp > 64))
1040                        continue;
1041
1042                error = rate - clock / (brp * (1 + tseg / 2));
1043                if (error < 0)
1044                {
1045                        error = -error;
1046                }
1047
1048                if (error <= best_error)
1049                {
1050                        best_error = error;
1051                        best_tseg = tseg/2;
1052                        best_brp = brp-1;
1053                }
1054        }
1055
1056        if (best_error && (rate / best_error < 10))
1057        {
1058                printk("OCCAN: bitrate %d is not possible with %d Hz clock\n\r",rate, clock);
1059                return -2;
1060        }else if ( !result )
1061                return 0; /* nothing to store result in, but a valid bitrate can be calculated */
1062
1063        tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100;
1064
1065        if (tseg2 < 0)
1066        {
1067                tseg2 = 0;
1068        }
1069
1070        if (tseg2 > MAX_TSEG2)
1071        {
1072                tseg2 = MAX_TSEG2;
1073        }
1074
1075        tseg1 = best_tseg - tseg2 - 2;
1076
1077        if (tseg1 > MAX_TSEG1)
1078        {
1079                tseg1 = MAX_TSEG1;
1080                tseg2 = best_tseg - tseg1 - 2;
1081        }
1082
1083        result->btr0 = (sjw<<OCCAN_BUSTIM_SJW_BIT) | (best_brp&OCCAN_BUSTIM_BRP);
1084        result->btr1 = (0<<7) | (tseg2<<OCCAN_BUSTIM_TSEG2_BIT) | tseg1;
1085
1086        return 0;
1087}
1088
1089static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing)
1090{
1091        if ( !timing || !priv || !priv->regs)
1092                return -1;
1093
1094        WRITE_REG(priv, &priv->regs->bustim0, timing->btr0);
1095        WRITE_REG(priv, &priv->regs->bustim1, timing->btr1);
1096
1097        return 0;
1098}
1099
1100#if 0
1101static unsigned int pelican_speed_auto_steplist [] = {
1102        OCCAN_SPEED_500K,
1103        OCCAN_SPEED_250K,
1104        OCCAN_SPEED_125K,
1105        OCCAN_SPEED_75K,
1106        OCCAN_SPEED_50K,
1107        OCCAN_SPEED_25K,
1108        OCCAN_SPEED_10K,
1109        0
1110};
1111#endif
1112
1113static int pelican_speed_auto(occan_priv *priv){
1114        return -1;
1115
1116#if 0
1117        int i=0;
1118        occan_speed_regs timing;
1119        unsigned int speed;
1120        unsigned char tmp;
1121
1122        while ( (speed=pelican_speed_auto_steplist[i]) > 0){
1123
1124                /* Reset core */
1125                WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET);
1126
1127                /* tell int handler about the auto speed detection test */
1128
1129
1130                /* wait for a moment (10ms) */
1131                /*usleep(10000);*/
1132
1133                /* No acceptance filter */
1134                pelican_set_accept(priv);
1135
1136                /* calc timing params for this */
1137                if ( occan_calc_speedregs(priv->sys_freq_hz,speed,&timing) ){
1138                        /* failed to get good timings for this frequency
1139                         * test with next
1140                         */
1141                         continue;
1142                }
1143
1144                timing.sam = 0;
1145
1146                /* set timing params for this speed */
1147                occan_set_speedregs(priv,&timing);
1148
1149                /* Empty previous messages in hardware RX fifo */
1150                /*
1151                while( READ_REG(priv, &priv->regs->) ){
1152
1153                }
1154                */
1155
1156                /* Clear pending interrupts */
1157                tmp = READ_REG(priv, &priv->regs->intflags);
1158
1159                /* enable RX & ERR interrupt */
1160                priv->regs->inten =
1161
1162                /* Get out of reset state */
1163                priv->regs->mode = PELICAN_MOD_LISTEN;
1164
1165                /* wait for frames or errors */
1166                while(1){
1167                        /* sleep 10ms */
1168
1169                }
1170
1171        }
1172#endif
1173}
1174
1175static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg)
1176{
1177        return RTEMS_SUCCESSFUL;
1178}
1179
1180static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1181{
1182        occan_priv *can;
1183        struct drvmgr_dev *dev;
1184
1185        DBG("OCCAN: Opening %d\n\r",minor);
1186
1187        /* get can device */   
1188        if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1189                DBG("Wrong minor %d\n", minor);
1190                return RTEMS_UNSATISFIED; /* NODEV */
1191        }
1192        can = (occan_priv *)dev->priv;
1193
1194        /* already opened? */
1195        rtems_semaphore_obtain(can->devsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1196        if ( can->open ){
1197                rtems_semaphore_release(can->devsem);
1198                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1199        }
1200        can->open = 1;
1201        rtems_semaphore_release(can->devsem);
1202
1203        SPIN_INIT(&can->devlock, can->devName);
1204
1205        /* allocate fifos */
1206        can->rxfifo = occan_fifo_create(DEFAULT_RX_FIFO_LEN);
1207        if ( !can->rxfifo ){
1208                can->open = 0;
1209                return RTEMS_NO_MEMORY; /* ENOMEM */
1210        }
1211
1212        can->txfifo = occan_fifo_create(DEFAULT_TX_FIFO_LEN);
1213        if ( !can->txfifo ){
1214                occan_fifo_free(can->rxfifo);
1215                can->rxfifo= NULL;
1216                can->open = 0;
1217                return RTEMS_NO_MEMORY; /* ENOMEM */
1218        }
1219
1220        DBG("OCCAN: Opening %d success\n\r",minor);
1221
1222        can->started = 0;
1223        can->channel = 0; /* Default to first can link */
1224        can->txblk = 1; /* Default to Blocking mode */
1225        can->rxblk = 1; /* Default to Blocking mode */
1226        can->single_mode = 1; /* single mode acceptance filter */
1227
1228        /* reset stat counters */
1229        memset(&can->stats,0,sizeof(occan_stats));
1230
1231        /* HW must be in reset mode here (close and initializes resets core...)
1232         *
1233         * 1. set default modes/speeds
1234         */
1235        pelican_open(can);
1236
1237        return RTEMS_SUCCESSFUL;
1238}
1239
1240static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1241{
1242        occan_priv *can;
1243        struct drvmgr_dev *dev;
1244
1245        DBG("OCCAN: Closing %d\n\r",minor);
1246
1247        if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1248                return RTEMS_INVALID_NAME;
1249        }
1250        can = (occan_priv *)dev->priv;
1251
1252        /* stop if running */
1253        if ( can->started )
1254                pelican_stop(can);
1255
1256        /* Enter Reset Mode */
1257        WRITE_REG(can, &can->regs->mode, PELICAN_MOD_RESET);
1258
1259        /* free fifo memory */
1260        occan_fifo_free(can->rxfifo);
1261        occan_fifo_free(can->txfifo);
1262
1263        can->rxfifo = NULL;
1264        can->txfifo = NULL;
1265
1266        can->open = 0;
1267
1268        return RTEMS_SUCCESSFUL;
1269}
1270
1271static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1272{
1273        occan_priv *can;
1274        struct drvmgr_dev *dev;
1275        rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1276        CANMsg *dstmsg, *srcmsg;
1277        SPIN_IRQFLAGS(oldLevel);
1278        int left;
1279
1280        if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1281                return RTEMS_INVALID_NAME;
1282        }
1283        can = (occan_priv *)dev->priv;
1284
1285        if ( !can->started ){
1286                DBG("OCCAN: cannot read from minor %d when not started\n\r",minor);
1287                return RTEMS_RESOURCE_IN_USE; /* -EBUSY*/
1288        }
1289
1290        /* does at least one message fit */
1291        left = rw_args->count;
1292        if ( left < sizeof(CANMsg) ){
1293                DBG("OCCAN: minor %d length of buffer must be at least %d, our is %d\n\r",minor,sizeof(CANMsg),left);
1294                return  RTEMS_INVALID_NAME; /* -EINVAL */
1295        }
1296
1297        /* get pointer to start where to put CAN messages */
1298        dstmsg = (CANMsg *)rw_args->buffer;
1299        if ( !dstmsg ){
1300                DBG("OCCAN: minor %d read: input buffer is NULL\n\r",minor);
1301                return  RTEMS_INVALID_NAME; /* -EINVAL */
1302        }
1303
1304        while (left >= sizeof(CANMsg) ){
1305
1306                /* turn off interrupts */
1307                SPIN_LOCK_IRQ(&can->devlock, oldLevel);
1308
1309                /* A bus off interrupt may have occured after checking can->started */
1310                if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1311                        SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1312                        DBG("OCCAN: read is cancelled due to a BUS OFF error\n\r");
1313                        rw_args->bytes_moved = rw_args->count-left;
1314                        return RTEMS_IO_ERROR; /* EIO */
1315                }
1316
1317                srcmsg = occan_fifo_claim_get(can->rxfifo);
1318                if ( !srcmsg ){
1319                        /* no more messages in reception fifo.
1320                         * Wait for incoming packets only if in
1321                         * blocking mode AND no messages been
1322                         * read before.
1323                         */
1324                        if ( !can->rxblk || (left != rw_args->count) ){
1325                                /* turn on interrupts again */
1326                                SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1327                                break;
1328                        }
1329
1330                        /* turn on interrupts again */
1331                        SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1332
1333                        DBG("OCCAN: Waiting for RX int\n\r");
1334
1335                        /* wait for incoming messages */
1336                        rtems_semaphore_obtain(can->rxsem, RTEMS_WAIT,
1337                                RTEMS_NO_TIMEOUT);
1338
1339                        /* did we get woken up by a BUS OFF error? */
1340                        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1341                                DBG("OCCAN: Blocking read got woken up by BUS OFF error\n\r");
1342                                /* At this point it should not matter how many messages we handled */
1343                                rw_args->bytes_moved = rw_args->count-left;
1344                                return RTEMS_IO_ERROR; /* EIO */
1345                        }
1346
1347                        /* no errors detected, it must be a message */
1348                        continue;
1349                }
1350
1351                /* got message, copy it to userspace buffer */
1352                *dstmsg = *srcmsg;
1353
1354                /* Return borrowed message, RX interrupt can use it again */
1355                occan_fifo_get(can->rxfifo);
1356
1357                /* turn on interrupts again */
1358                SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1359
1360                /* increase pointers */
1361                left -= sizeof(CANMsg);
1362                dstmsg++;
1363        }
1364
1365        /* save number of read bytes. */
1366        rw_args->bytes_moved = rw_args->count-left;
1367        if ( rw_args->bytes_moved == 0 ){
1368                DBG("OCCAN: minor %d read would block, returning\n\r",minor);
1369                return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1370        }
1371        return RTEMS_SUCCESSFUL;
1372}
1373
1374static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1375{
1376        occan_priv *can;
1377        struct drvmgr_dev *dev;
1378        rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1379        CANMsg *msg,*fifo_msg;
1380        SPIN_IRQFLAGS(oldLevel);
1381        int left;
1382
1383        DBG("OCCAN: Writing %d bytes from 0x%lx (%d)\n\r",rw_args->count,rw_args->buffer,sizeof(CANMsg));
1384
1385        if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1386                return RTEMS_INVALID_NAME;
1387        }
1388        can = (occan_priv *)dev->priv;
1389
1390        if ( !can->started )
1391                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1392
1393        left = rw_args->count;
1394        if ( (left < sizeof(CANMsg)) || (!rw_args->buffer) ){
1395                return RTEMS_INVALID_NAME; /* EINVAL */
1396        }
1397
1398        msg = (CANMsg *)rw_args->buffer;
1399
1400        /* limit CAN message length to 8 */
1401        msg->len = (msg->len > 8) ? 8 : msg->len;
1402
1403#ifdef DEBUG_VERBOSE
1404        pelican_regs_print(can->regs);
1405        occan_stat_print(&can->stats);
1406#endif
1407
1408        /* turn off interrupts */
1409        SPIN_LOCK_IRQ(&can->devlock, oldLevel);
1410
1411        /* A bus off interrupt may have occured after checking can->started */
1412        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1413                SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1414                rw_args->bytes_moved = 0;
1415                return RTEMS_IO_ERROR; /* EIO */
1416        }
1417
1418        /* If no messages in software tx fifo, we will
1419         * try to send first message by putting it directly
1420         * into the HW TX fifo.
1421         */
1422        if ( occan_fifo_empty(can->txfifo) ){
1423                /*pelican_regs_print(cans[minor+1].regs);*/
1424                if ( !pelican_send(can,msg) ) {
1425                        /* First message put directly into HW TX fifo
1426                         * This will turn TX interrupt on.
1427                         */
1428                        left -= sizeof(CANMsg);
1429                        msg++;
1430
1431#ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1432                        /* Mark that we have put at least one msg in TX FIFO */
1433                        can->sending = 1;
1434#endif
1435
1436                        /* bump stat counters */
1437                        can->stats.tx_msgs++;
1438
1439                        DBG("OCCAN: Sending direct via HW\n\r");
1440                }
1441        }
1442
1443        /* Put messages into software fifo */
1444        while ( left >= sizeof(CANMsg) ){
1445
1446                /* limit CAN message length to 8 */
1447                msg->len = (msg->len > 8) ? 8 : msg->len;
1448
1449                fifo_msg = occan_fifo_put_claim(can->txfifo,0);
1450                if ( !fifo_msg ){
1451
1452                        DBG("OCCAN: FIFO is full\n\r");
1453                        /* Block only if no messages previously sent
1454                         * and no in blocking mode
1455                         */
1456                        if ( !can->txblk  || (left != rw_args->count) )
1457                                break;
1458
1459                        /* turn on interupts again and wait
1460                                INT_ON
1461                                WAIT FOR FREE BUF;
1462                                INT_OFF;
1463                                CHECK_IF_FIFO_EMPTY ==> SEND DIRECT VIA HW;
1464                        */
1465                        SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1466
1467                        DBG("OCCAN: Waiting for tx int\n\r");
1468
1469                        rtems_semaphore_obtain(can->txsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1470
1471                        /* did we get woken up by a BUS OFF error? */
1472                        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1473                                DBG("OCCAN: Blocking write got woken up by BUS OFF error or RESET event\n\r");
1474                                /* At this point it should not matter how many messages we handled */
1475                                rw_args->bytes_moved = rw_args->count-left;
1476                                return RTEMS_IO_ERROR; /* EIO */
1477                        }
1478
1479                        SPIN_LOCK_IRQ(&can->devlock, oldLevel);
1480
1481                        if ( occan_fifo_empty(can->txfifo) ){
1482                                if ( !pelican_send(can,msg) ) {
1483                                        /* First message put directly into HW TX fifo
1484                                         * This will turn TX interrupt on.
1485                                         */
1486                                        left -= sizeof(CANMsg);
1487                                        msg++;
1488
1489#ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1490                                        /* Mark that we have put at least one msg in TX FIFO */
1491                                        can->sending = 1;
1492#endif
1493
1494                                        /* bump stat counters */
1495                                        can->stats.tx_msgs++;
1496
1497                                        DBG("OCCAN: Sending direct2 via HW\n\r");
1498                                }
1499                        }
1500                        continue;
1501                }
1502
1503                /* copy message into fifo area */
1504                *fifo_msg = *msg;
1505
1506                /* tell interrupt handler about the message */
1507                occan_fifo_put(can->txfifo);
1508
1509                DBG("OCCAN: Put info fifo SW\n\r");
1510
1511                /* Prepare insert of next message */
1512                msg++;
1513                left-=sizeof(CANMsg);
1514        }
1515
1516        SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1517
1518        rw_args->bytes_moved = rw_args->count-left;
1519        DBG("OCCAN: Sent %d\n\r",rw_args->bytes_moved);
1520
1521        if ( left == rw_args->count )
1522                return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1523        return RTEMS_SUCCESSFUL;
1524}
1525
1526static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1527{
1528        int ret;
1529        occan_speed_regs timing;
1530        occan_priv *can;
1531        struct drvmgr_dev *dev;
1532        unsigned int speed;
1533        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1534        struct occan_afilter *afilter;
1535        occan_stats *dststats;
1536        unsigned int rxcnt,txcnt;
1537
1538        DBG("OCCAN: IOCTL %d\n\r",ioarg->command);
1539
1540        if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1541                return RTEMS_INVALID_NAME;
1542        }
1543        can = (occan_priv *)dev->priv;
1544
1545        ioarg->ioctl_return = 0;
1546        switch(ioarg->command){
1547                case OCCAN_IOC_SET_SPEED:
1548
1549                        /* cannot change speed during run mode */
1550                        if ( can->started )
1551                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1552
1553                        /* get speed rate from argument */
1554                        speed = (unsigned int)ioarg->buffer;
1555                        ret = occan_calc_speedregs(can->sys_freq_hz,speed,&timing);
1556                        if ( ret )
1557                                return  RTEMS_INVALID_NAME; /* EINVAL */
1558
1559                        /* set the speed regs of the CAN core */
1560                        /* occan_set_speedregs(can,timing); */
1561
1562                        /* save timing/speed */
1563                        can->speed = speed;
1564                        can->timing = timing;
1565                        break;
1566
1567                case OCCAN_IOC_SET_BTRS:
1568                        /* Set BTR registers manually
1569                         * Read OCCAN Manual.
1570                         */
1571                        if ( can->started )
1572                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1573
1574                        can->speed = 0; /* custom */
1575                        can->timing.btr1 = (unsigned int)ioarg->buffer & 0xff;
1576                        can->timing.btr0 = ((unsigned int)ioarg->buffer>>8) & 0xff;
1577/*
1578                        can->timing.sjw = (btr0 >> OCCAN_BUSTIM_SJW_BIT) & 0x3;
1579                        can->timing.brp = btr0 & OCCAN_BUSTIM_BRP;
1580                        can->timing.tseg1 = btr1 & 0xf;
1581                        can->timing.tseg2 = (btr1 >> OCCAN_BUSTIM_TSEG2_BIT) & 0x7;
1582                        can->timing.sam = (btr1 >> 7) & 0x1;
1583                        */
1584                        break;
1585
1586                case OCCAN_IOC_SPEED_AUTO:
1587                        return RTEMS_NOT_IMPLEMENTED;
1588                        if ( can->started )
1589                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1590
1591                        if ( (speed=pelican_speed_auto(can)) < 0 ){
1592                                /* failed */
1593                                return RTEMS_IO_ERROR;
1594                        }
1595
1596                        /* set new speed */
1597                        can->speed = speed;
1598
1599                        if ( (int *)ioarg->buffer ){
1600                                *(int *)ioarg->buffer = speed;
1601                        }
1602                        return RTEMS_SUCCESSFUL;
1603                        break;
1604
1605                case OCCAN_IOC_SET_BUFLEN:
1606                        /* set rx & tx fifo buffer length */
1607                        if ( can->started )
1608                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1609
1610                        rxcnt = (unsigned int)ioarg->buffer & 0x0000ffff;
1611                        txcnt = (unsigned int)ioarg->buffer >> 16;
1612
1613                        occan_fifo_free(can->rxfifo);
1614                        occan_fifo_free(can->txfifo);
1615
1616                        /* allocate new buffers */
1617                        can->rxfifo = occan_fifo_create(rxcnt);
1618                        can->txfifo = occan_fifo_create(txcnt);
1619
1620                        if ( !can->rxfifo || !can->txfifo )
1621                                return RTEMS_NO_MEMORY; /* ENOMEM */
1622                        break;
1623
1624                case OCCAN_IOC_GET_CONF:
1625                        return RTEMS_NOT_IMPLEMENTED;
1626                        break;
1627
1628                case OCCAN_IOC_GET_STATS:
1629                        dststats = (occan_stats *)ioarg->buffer;
1630                        if ( !dststats )
1631                                return  RTEMS_INVALID_NAME; /* EINVAL */
1632
1633                        /* copy data stats into userspace buffer */
1634                        if ( can->rxfifo )
1635                                can->stats.rx_sw_dovr = can->rxfifo->ovcnt;
1636                        *dststats = can->stats;
1637                        break;
1638
1639                case OCCAN_IOC_GET_STATUS:
1640                        /* return the status of the */
1641                        if ( !ioarg->buffer )
1642                                return RTEMS_INVALID_NAME;
1643
1644                        *(unsigned int *)ioarg->buffer = can->status;
1645                        break;
1646
1647                /* Set physical link */
1648                case OCCAN_IOC_SET_LINK:
1649#ifdef REDUNDANT_CHANNELS
1650                        if ( can->started )
1651                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1652
1653                        /* switch HW channel */
1654                        can->channel = (unsigned int)ioargs->buffer;
1655#else
1656                        return RTEMS_NOT_IMPLEMENTED;
1657#endif
1658                        break;
1659
1660                case OCCAN_IOC_SET_FILTER:
1661                        if ( can->started )
1662                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1663
1664                        afilter = (struct occan_afilter *)ioarg->buffer;
1665
1666                        if ( !afilter )
1667                                return RTEMS_INVALID_NAME; /* EINVAL */
1668
1669                        /* copy acceptance filter */
1670                        can->acode[0] = afilter->code[0];
1671                        can->acode[1] = afilter->code[1];
1672                        can->acode[2] = afilter->code[2];
1673                        can->acode[3] = afilter->code[3];
1674
1675                        can->amask[0] = afilter->mask[0];
1676                        can->amask[1] = afilter->mask[1];
1677                        can->amask[2] = afilter->mask[2];
1678                        can->amask[3] = afilter->mask[3];
1679
1680                        can->single_mode = ( afilter->single_mode ) ? 1 : 0;
1681
1682                        /* Acceptance filter is written to hardware
1683                         * when starting.
1684                         */
1685                        /* pelican_set_accept(can,can->acode,can->amask);*/
1686                        break;
1687
1688                case OCCAN_IOC_SET_BLK_MODE:
1689                        can->rxblk = (unsigned int)ioarg->buffer & OCCAN_BLK_MODE_RX;
1690                        can->txblk = ((unsigned int)ioarg->buffer & OCCAN_BLK_MODE_TX) >> 1;
1691                        break;
1692
1693                case OCCAN_IOC_START:
1694                        if ( can->started )
1695                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1696                        if ( pelican_start(can) )
1697                                return RTEMS_NO_MEMORY; /* failed because of no memory, can happen if SET_BUFLEN failed */
1698                        /* can->started = 1; -- Is set in pelican_start due to interrupt may occur before we
1699                         * get here.
1700                         */
1701                        break;
1702
1703                case OCCAN_IOC_STOP:
1704                        if ( !can->started )
1705                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1706                        pelican_stop(can);
1707                        can->started = 0;
1708                        break;
1709
1710                default:
1711                        return RTEMS_NOT_DEFINED;
1712        }
1713        return RTEMS_SUCCESSFUL;
1714}
1715
1716void occan_interrupt(void *arg)
1717{
1718        occan_priv *can = arg;
1719        unsigned char iflags;
1720        pelican_regs *regs = can->regs;
1721        CANMsg *msg;
1722        int signal_rx=0, signal_tx=0;
1723        unsigned char tmp, errcode, arbcode;
1724        int tx_error_cnt,rx_error_cnt;
1725        SPIN_ISR_IRQFLAGS(irqflags);
1726
1727        if ( !can->started )
1728                return; /* Spurious Interrupt, do nothing */
1729
1730        SPIN_LOCK(&can->devlock, irqflags);
1731        while (1) {
1732
1733                iflags = READ_REG(can, &can->regs->intflags);
1734
1735#ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1736                /* TX IRQ may be cleared when reading regs->intflags due
1737                 * to a bug in some chips. Instead of looking at the TX_IRQ_FLAG
1738                 * the TX-fifo emoty register is looked at when something has
1739                 * been scheduled for transmission.
1740                 */
1741                if ((iflags & PELICAN_IF_TX) == 0) {
1742                        if (can->sending && pelican_tx_ready(can)) {
1743                                can->sending = 0;
1744                                iflags |= PELICAN_IF_TX;
1745                        }
1746                }
1747#endif
1748
1749                if (iflags == 0)
1750                        break;
1751                /* still interrupts to handle */
1752
1753                can->stats.ints++;
1754
1755                if ( iflags & PELICAN_IF_RX ){
1756                        /* the rx fifo is not empty
1757                         * put 1 message into rxfifo for later use
1758                         */
1759
1760                        /* get empty (or make room) message */
1761                        msg = occan_fifo_put_claim(can->rxfifo,1);
1762                        tmp = READ_REG(can, &regs->rx_fi_xff);
1763                        msg->extended = tmp >> 7;
1764                        msg->rtr = (tmp >> 6) & 1;
1765                        msg->len = tmp = tmp & 0x0f;
1766
1767                        if ( msg->extended ){
1768                                /* extended message */
1769                                msg->id =  READ_REG(can, &regs->msg.rx_eff.id[0])<<(5+8+8) |
1770                                           READ_REG(can, &regs->msg.rx_eff.id[1])<<(5+8) |
1771                                           READ_REG(can, &regs->msg.rx_eff.id[2])<<5 |
1772                                           READ_REG(can, &regs->msg.rx_eff.id[3])>>3;
1773
1774                                while(tmp--){
1775                                        msg->data[tmp] = READ_REG(can, &regs->msg.rx_eff.data[tmp]);
1776                                }
1777                                /*
1778                                msg->data[0] = READ_REG(can, &regs->msg.rx_eff.data[0]);
1779                                msg->data[1] = READ_REG(can, &regs->msg.rx_eff.data[1]);
1780                                msg->data[2] = READ_REG(can, &regs->msg.rx_eff.data[2]);
1781                                msg->data[3] = READ_REG(can, &regs->msg.rx_eff.data[3]);
1782                                msg->data[4] = READ_REG(can, &regs->msg.rx_eff.data[4]);
1783                                msg->data[5] = READ_REG(can, &regs->msg.rx_eff.data[5]);
1784                                msg->data[6] = READ_REG(can, &regs->msg.rx_eff.data[6]);
1785                                msg->data[7] = READ_REG(can, &regs->msg.rx_eff.data[7]);
1786                                */
1787                        }else{
1788                                /* standard message */
1789                                msg->id = READ_REG(can, &regs->msg.rx_sff.id[0])<<3 |
1790                                          READ_REG(can, &regs->msg.rx_sff.id[1])>>5;
1791
1792                                while(tmp--){
1793                                        msg->data[tmp] = READ_REG(can, &regs->msg.rx_sff.data[tmp]);
1794                                }
1795                                /*
1796                                msg->data[0] = READ_REG(can, &regs->msg.rx_sff.data[0]);
1797                                msg->data[1] = READ_REG(can, &regs->msg.rx_sff.data[1]);
1798                                msg->data[2] = READ_REG(can, &regs->msg.rx_sff.data[2]);
1799                                msg->data[3] = READ_REG(can, &regs->msg.rx_sff.data[3]);
1800                                msg->data[4] = READ_REG(can, &regs->msg.rx_sff.data[4]);
1801                                msg->data[5] = READ_REG(can, &regs->msg.rx_sff.data[5]);
1802                                msg->data[6] = READ_REG(can, &regs->msg.rx_sff.data[6]);
1803                                msg->data[7] = READ_REG(can, &regs->msg.rx_sff.data[7]);
1804                                */
1805                        }
1806
1807                        /* Re-Enable RX buffer for a new message */
1808                        WRITE_REG(can, &regs->cmd, PELICAN_CMD_RELRXBUF);
1809
1810                        /* make message available to the user */
1811                        occan_fifo_put(can->rxfifo);
1812
1813                        /* bump stat counters */
1814                        can->stats.rx_msgs++;
1815
1816                        /* signal the semaphore only once */
1817                        signal_rx = 1;
1818                }
1819
1820                if ( iflags & PELICAN_IF_TX ) {
1821
1822                        /* there is room in tx fifo of HW */
1823
1824                        if ( !occan_fifo_empty(can->txfifo) ){
1825                                /* send 1 more messages */
1826                                msg = occan_fifo_claim_get(can->txfifo);
1827
1828                                if ( pelican_send(can,msg) ){
1829                                        /* ERROR! We got an TX interrupt telling us
1830                                         * tx fifo is empty, yet it is not.
1831                                         *
1832                                         * Complain about this max 10 times
1833                                         */
1834                                        if ( can->stats.tx_buf_error < 10 ){
1835                                                printk("OCCAN: got TX interrupt but TX fifo in not empty (%d)\n\r",can->stats.tx_buf_error);
1836                                        }
1837                                        can->status |= OCCAN_STATUS_QUEUE_ERROR;
1838                                        can->stats.tx_buf_error++;
1839                                }
1840#ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1841                                can->sending = 1;
1842#endif
1843
1844                                /* free software-fifo space taken by sent message */
1845                                occan_fifo_get(can->txfifo);
1846
1847                                /* bump stat counters */
1848                                can->stats.tx_msgs++;
1849
1850                                /* wake any sleeping thread waiting for "fifo not full" */
1851                                signal_tx = 1;
1852                        }
1853                }
1854
1855                if ( iflags & PELICAN_IF_ERRW ){
1856                        tx_error_cnt = READ_REG(can, &regs->tx_err_cnt);
1857                        rx_error_cnt = READ_REG(can, &regs->rx_err_cnt);
1858
1859                        /* 1. if bus off tx error counter = 127 */
1860                        if ( (tx_error_cnt > 96) || (rx_error_cnt > 96) ){
1861                                /* in Error Active Warning area or BUS OFF */
1862                                can->status |= OCCAN_STATUS_WARN;
1863
1864                                /* check reset bit for reset mode */
1865                                if ( READ_REG(can, &regs->mode) & PELICAN_MOD_RESET ){
1866                                        /* in reset mode ==> bus off */
1867                                        can->status |= OCCAN_STATUS_ERR_BUSOFF | OCCAN_STATUS_RESET;
1868
1869                                        /***** pelican_stop(can) ******
1870                                         * turn off interrupts
1871                                         * enter reset mode (HW already done that for us)
1872                                         */
1873                                        WRITE_REG(can, &regs->inten,0);
1874
1875                                        /* Indicate that we are not started any more.
1876                                         * This will make write/read return with EBUSY
1877                                         * on read/write attempts.
1878                                         *
1879                                         * User must issue a ioctl(START) to get going again.
1880                                         */
1881                                        can->started = 0;
1882
1883                                        /* signal any waiting read/write threads, so that they
1884                                         * can handle the bus error.
1885                                         */
1886                                        signal_rx = 1;
1887                                        signal_tx = 1;
1888
1889                                        /* ingnore any old pending interrupt */
1890                                        break;
1891                                }
1892
1893                        }else{
1894                                /* not in Upper Error Active area any more */
1895                                can->status &= ~(OCCAN_STATUS_WARN);
1896                        }
1897                        can->stats.err_warn++;
1898                }
1899
1900                if ( iflags & PELICAN_IF_DOVR){
1901                        can->status |= OCCAN_STATUS_OVERRUN;
1902                        can->stats.err_dovr++;
1903                        DBG("OCCAN_INT: DOVR\n\r");
1904                }
1905
1906                if ( iflags & PELICAN_IF_ERRP){
1907                        /* Let the error counters decide what kind of
1908                         * interrupt it was. In/Out of EPassive area.
1909                         */
1910                        tx_error_cnt = READ_REG(can, &regs->tx_err_cnt);
1911                        rx_error_cnt = READ_REG(can, &regs->rx_err_cnt);
1912
1913                        if ( (tx_error_cnt > 127) || (rx_error_cnt > 127) ){
1914                                can->status |= OCCAN_STATUS_ERR_PASSIVE;
1915                        }else{
1916                                can->status &= ~(OCCAN_STATUS_ERR_PASSIVE);
1917                        }
1918
1919                        /* increase Error Passive In/out interrupt counter */
1920                        can->stats.err_errp++;
1921                }
1922
1923                if ( iflags & PELICAN_IF_ARB){
1924                        arbcode = READ_REG(can, &regs->arbcode);
1925                        can->stats.err_arb_bitnum[arbcode & PELICAN_ARB_BITS]++;
1926                        can->stats.err_arb++;
1927                        DBG("OCCAN_INT: ARB (0x%x)\n\r",arbcode & PELICAN_ARB_BITS);
1928                }
1929
1930                if ( iflags & PELICAN_IF_BUS){
1931                        /* Some kind of BUS error, only used for
1932                         * statistics. Error Register is decoded
1933                         * and put into can->stats.
1934                         */
1935                        errcode = READ_REG(can, &regs->errcode);
1936                        switch( errcode & PELICAN_ECC_CODE ){
1937                                case PELICAN_ECC_CODE_BIT:
1938                                        can->stats.err_bus_bit++;
1939                                        break;
1940                                case PELICAN_ECC_CODE_FORM:
1941                                        can->stats.err_bus_form++;
1942                                        break;
1943                                case PELICAN_ECC_CODE_STUFF:
1944                                        can->stats.err_bus_stuff++;
1945                                        break;
1946                                case PELICAN_ECC_CODE_OTHER:
1947                                        can->stats.err_bus_other++;
1948                                        break;
1949                        }
1950
1951                        /* Get Direction (TX/RX) */
1952                        if ( errcode & PELICAN_ECC_DIR ){
1953                                can->stats.err_bus_rx++;
1954                        }else{
1955                                can->stats.err_bus_tx++;
1956                        }
1957
1958                        /* Get Segment in frame that went wrong */
1959                        can->stats.err_bus_segs[errcode & PELICAN_ECC_SEG]++;
1960
1961                        /* total number of bus errors */
1962                        can->stats.err_bus++;
1963                }
1964        }
1965        SPIN_UNLOCK(&can->devlock, irqflags);
1966
1967        /* signal Binary semaphore, messages available! */
1968        if ( signal_rx ){
1969                rtems_semaphore_release(can->rxsem);
1970        }
1971
1972        if ( signal_tx ){
1973                rtems_semaphore_release(can->txsem);
1974        }
1975}
1976
1977/*******************************************************************************
1978 * FIFO IMPLEMENTATION
1979 */
1980
1981static occan_fifo *occan_fifo_create(int cnt)
1982{
1983        occan_fifo *fifo;
1984        fifo = malloc(sizeof(occan_fifo)+cnt*sizeof(CANMsg));
1985        if ( fifo ){
1986                fifo->cnt = cnt;
1987                fifo->full = 0;
1988                fifo->ovcnt = 0;
1989                fifo->base = (CANMsg *)&fifo->fifoarea[0];
1990                fifo->tail = fifo->head = fifo->base;
1991                /* clear CAN Messages */
1992                memset(fifo->base,0,cnt * sizeof(CANMsg));
1993        }
1994        return fifo;
1995}
1996
1997static void occan_fifo_free(occan_fifo *fifo)
1998{
1999        if ( fifo )
2000                free(fifo);
2001}
2002
2003static int occan_fifo_full(occan_fifo *fifo)
2004{
2005        return fifo->full;
2006}
2007
2008static int occan_fifo_empty(occan_fifo *fifo)
2009{
2010        return (!fifo->full) && (fifo->head == fifo->tail);
2011}
2012
2013/* Stage 1 - get buffer to fill (never fails if force!=0) */
2014static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force)
2015{
2016        if ( !fifo )
2017                return NULL;
2018
2019        if ( occan_fifo_full(fifo) ){
2020
2021                if ( !force )
2022                        return NULL;
2023
2024                /* all buffers already used ==> overwrite the oldest */
2025                fifo->ovcnt++;
2026                occan_fifo_get(fifo);
2027        }
2028
2029        return fifo->head;
2030}
2031
2032/* Stage 2 - increment indexes */
2033static void occan_fifo_put(occan_fifo *fifo)
2034{
2035        if ( occan_fifo_full(fifo) )
2036                return;
2037
2038        /* wrap around */
2039        fifo->head = (fifo->head >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->head+1;
2040
2041        if ( fifo->head == fifo->tail )
2042                fifo->full = 1;
2043}
2044
2045static CANMsg *occan_fifo_claim_get(occan_fifo *fifo)
2046{
2047        if ( occan_fifo_empty(fifo) )
2048                return NULL;
2049
2050        /* return oldest message */
2051        return fifo->tail;
2052}
2053
2054
2055static void occan_fifo_get(occan_fifo *fifo)
2056{
2057        if ( !fifo )
2058                return;
2059
2060        if ( occan_fifo_empty(fifo) )
2061                return;
2062
2063        /* increment indexes */
2064        fifo->tail = (fifo->tail >= &fifo->base[fifo->cnt-1]) ?
2065                     fifo->base : fifo->tail+1;
2066        fifo->full = 0;
2067}
2068
2069static void occan_fifo_clr(occan_fifo *fifo)
2070{
2071        fifo->full  = 0;
2072        fifo->ovcnt = 0;
2073        fifo->head  = fifo->tail = fifo->base;
2074}
2075
2076/******************************************************************************/
Note: See TracBrowser for help on using the repository browser.