]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/can/m68k/mcf52xx/v2_0/src/can_mcf52xx.c
Initial revision
[karo-tx-redboot.git] / packages / devs / can / m68k / mcf52xx / v2_0 / src / can_mcf52xx.c
1 //==========================================================================
2 //
3 //      devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
4 //
5 //      CAN driver for Motorola coldfire processors
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    Uwe Kindler
45 // Contributors: Uwe Kindler
46 // Date:         2005-05-12
47 // Purpose:      support coldfire on-chip flexcan moduls
48 // Description: 
49 //
50 //####DESCRIPTIONEND####
51 //
52 //==========================================================================
53
54
55 //==========================================================================
56 //                              INCLUDES
57 //==========================================================================
58 #include <pkgconf/system.h>
59 #include <pkgconf/io_can.h>
60 #include <pkgconf/devs_can_mcf52xx_flexcan.h>
61
62 #include <cyg/infra/diag.h>
63
64 #include <cyg/io/io.h>
65 #include <cyg/io/devtab.h>
66 #include <cyg/io/can.h>
67
68 #include <cyg/hal/hal_arch.h>
69 #include <cyg/hal/hal_intr.h>
70 #include <cyg/hal/hal_io.h>
71
72
73 //===========================================================================
74 //                                DEFINES  
75 //===========================================================================
76
77 //
78 // we define our own ste of register bits in order to be independent from
79 // platform specific names
80 //
81
82 //---------------------------------------------------------------------------
83 // MCR regsiter bits
84 //
85 #define FLEXCAN_MCR_STOP                    (0x01 << 15)
86 #define FLEXCAN_MCR_FRZ                     (0x01 << 14)
87 #define FLEXCAN_MCR_HALT                    (0x01 << 12)
88 #define FLEXCAN_MCR_NOTRDY                  (0x01 << 11)
89 #define FLEXCAN_MCR_WAKEMSK                 (0x01 << 10)
90 #define FLEXCAN_MCR_SOFTRST                 (0x01 << 9)
91 #define FLEXCAN_MCR_FRZACK                  (0x01 << 8)
92 #define FLEXCAN_MCR_SUPV                    (0x01 << 7)
93 #define FLEXCAN_MCR_SELFWAKE                (0x01 << 6)
94 #define FLEXCAN_MCR_APS                     (0x01 << 5)
95 #define FLEXCAN_MCR_STOPACK                 (0x01 << 4)
96
97
98 //---------------------------------------------------------------------------
99 // CTRL0 register bits
100 //
101 #define FLEXCAN_CTRL0_BOFFMSK                   (0x01 << 7)
102 #define FLEXCAN_CTRL0_ERRMASK                   (0x01 << 6)
103 #define FLEXCAN_CTRL0_RXMODE                    (0x01 << 2)
104 #define FLEXCAN_CTRL0_RXMODE_0_DOMINANT         (0x00 << 2)
105 #define FLEXCAN_CTRL0_RXMODE_1_DOMINANT         (0x01 << 2)
106 #define FLEXCAN_CTRL0_TXMODE_MASK               (0x03 << 0)
107 #define FLEXCAN_CTRL0_TXMODE_SHIFT              0
108 #define FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT    (0x00 << 0)
109 #define FLEXCAN_CTRL0_TXMODE_FULL_1_DOMINANT    (0x01 << 0)
110 #define FLEXCAN_CTRL0_TXMODE_OPEN_0_DOMINANT    (0x02 << 0)
111
112
113 //---------------------------------------------------------------------------
114 // CTRL1 register bits
115 //
116 #define FLEXCAN_CTRL1_SAMP                      (0x01 << 7)
117 #define FLEXCAN_CTRL1_TSYNC                     (0x01 << 5)
118 #define FLEXCAN_CTRL1_LBUF                      (0x01 << 4)
119 #define FLEXCAN_CTRL1_LOM                       (0x01 << 3)
120 #define FLEXCAN_CTRL1_PROPSEG_MASK              (0x07 << 0)
121 #define FLEXCAN_CTRL1_PROPSEG_SHIFT             0
122
123
124 //---------------------------------------------------------------------------
125 // CTRL2 register bits
126 //
127 #define FLEXCAN_CTRL2_RJW_MASK                  (0x03 << 6)
128 #define FLEXCAN_CTRL2_RJW_SHIFT                 6
129 #define FLEXCAN_CTRL2_PSEG1_MASK                (0x07 << 3)
130 #define FLEXCAN_CTRL2_PSEG1_SHIFT               3
131 #define FLEXCAN_CTRL2_PSEG2_MASK                (0x07 << 0)
132 #define FLEXCAN_CTRL2_PSEG2_SHIFT               0
133
134 //---------------------------------------------------------------------------
135 // ESTAT register bits
136 //
137 #define FLEXCAN_ESTAT_BITERR_MASK               (0x03 << 14)
138 #define FLEXCAN_ESTAT_BITERR_SHIFT              14
139 #define FLEXCAN_ESTAT_BITERR_NONE               (0x00 << 14)
140 #define FLEXCAN_ESTAT_BITERR_DOMINANT_RECESSIVE (0x01 << 14)
141 #define FLEXCAN_ESTAT_BITERR_RECESSIVE_DOMINANT (0x02 << 14)
142 #define FLEXCAN_ESTAT_ACKERR                    (0x01 << 13)
143 #define FLEXCAN_ESTAT_CRCERR                    (0x01 << 12)
144 #define FLEXCAN_ESTAT_FORMERR                   (0x01 << 11)
145 #define FLEXCAN_ESTAT_STUFFERR                  (0x01 << 10)
146 #define FLEXCAN_ESTAT_TXWARN                    (0x01 << 9)
147 #define FLEXCAN_ESTAT_RXWARN                    (0x01 << 8)
148 #define FLEXCAN_ESTAT_IDLE                      (0x01 << 7)
149 #define FLEXCAN_ESTAT_TX_RX                     (0x01 << 6)
150 #define FLEXCAN_ESTAT_FCS_MASK                  (0x03 << 4)
151 #define FLEXCAN_ESTAT_FCS_SHIFT                 4
152 #define FLEXCAN_ESTAT_FCS_ERROR_ACTIVE          (0x00 << 4)
153 #define FLEXCAN_ESTAT_FCS_ERROR_PASSIVE         (0x01 << 4)
154 #define FLEXCAN_ESTAT_BOFFINT                   (0x01 << 2)
155 #define FLEXCAN_ESTAT_ERRINT                    (0x01 << 1)
156 #define FLEXCAN_ESTAT_WAKEINT                   (0x01 << 0)
157
158 //
159 // For receive event calls we use these two identifiers for
160 // err and bus off events - message boxes use 0 - 15
161 //
162 #define FLEXCAN_ERR_EVENT                       16
163 #define FLEXCAN_BUSOFF_EVENT                    17
164
165
166 //---------------------------------------------------------------------------
167 // message buffer cfg bits
168 //
169 #define MBOX_RXCODE_NOT_ACTIVE 0x00
170 #define MBOX_RXCODE_BUSY       0x10
171 #define MBOX_RXCODE_EMPTY      0x40
172 #define MBOX_RXCODE_FULL       0x20
173 #define MBOX_RXCODE_OVERRUN    0x60
174
175 #define MBOX_TXCODE_NOT_READY  0x80
176 #define MBOX_TXCODE_TRANSMIT   0xC0
177 #define MBOX_TXCODE_RESPONSE   0xA0
178
179 #define MBOX_DATA_FRAME        0x00 // data frame
180 #define MBOX_REMOTE_FRAME      0x01 // remote frame
181 #define MBOX_STD_ID            0x00 // standard identifier
182 #define MBOX_EXT_ID            0x01 // remote identifier
183 #define MBOX_TX                0x08 // tx message box
184 #define MBOX_RX                0x00 // rx messge box
185
186 #define MBOX_CFG_IDE           0x08
187 #define MBOX_CFG_RTR_EXT       0x01
188 #define MBOX_CFG_RTR_STD       0x10
189 #define MBOX_CFG_SSR           0x10
190 #define MBOX_CFG_DLC_MASK      0x0F
191 #define MBOX_CFG_STAT_MASK     0xF0
192
193
194 //===========================================================================
195 //                                 DATA TYPES
196 //===========================================================================
197 //
198 // configuration info for flexcan message buffer
199 //
200 typedef struct flexcan_mbox_info_st
201 {
202     cyg_vector_t  isr_vec;
203     int           isr_priority;
204     cyg_interrupt interrupt;
205     cyg_handle_t  interrupt_handle;   
206     cyg_uint8     num;  
207 } flexcan_mbox_info; 
208
209 //
210 // flexcan interrupt (busoff, err, wake) data
211 //
212 typedef struct flexcan_int_st
213 {
214     cyg_vector_t        isr_vec;  
215     int                 isr_priority;
216     cyg_interrupt       interrupt;
217     cyg_handle_t        interrupt_handle;
218 } flexcan_int;
219
220 //
221 // flexcan message box initialisation
222 //
223 #define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
224     isr_vec      : (_mbox0_vec) + (_mbox_no),            \
225     isr_priority : (_prio),                              \
226     num          : (_mbox_no)                            \
227 }
228
229 //
230 // Interrupt initialisation
231 //
232 #define FLEXCAN_INT_INIT(_vec, _prio) \
233 {                                     \
234     isr_vec      : (_vec),            \
235     isr_priority : (_prio)            \
236 }
237
238 //
239 // flexcan configuration 
240 //
241 typedef struct flexcan_info 
242 {
243     cyg_uint8          *base;          // base address of flexcan modul
244     cyg_vector_t        isr_vec_mbox0; // vector number of ISR vector of first message box
245     flexcan_mbox_info   rx_mbox;       // rx message box interrupt
246     flexcan_mbox_info   tx_mbox;       // tx message box interrupt
247     cyg_uint32          last_tx_id;    // last transmitted message
248     bool                tx_busy;       // indicates if transmit process ic currently running
249     
250     cyg_uint32          rxgmask;       // acceptance filter for message box 0 - 13
251     cyg_uint32          rx14mask;      // acceptance filter for message box 14
252     cyg_uint32          rx15mask;      // acceptance filter for message box 15
253     
254     flexcan_int         boff_int;      // bus off interrupt data
255     flexcan_int         err_int;       // error interrupt data
256  
257     cyg_uint32          timeout_rd;
258     cyg_uint32          timeout_wr;
259     cyg_uint16          mbox_alloc_flags;// these bits are used to indicate which message buffers are already alloceted and which ones are free
260 #ifdef FLEXCAN_CAN_STATS
261     cyg_uint32          isr_count;
262     cyg_uint32          dsr_count;
263     cyg_uint32          rx_bytes;
264     cyg_uint32          tx_bytes;
265     cyg_uint32          rx_errors;
266 #endif  
267 } flexcan_info;
268
269
270 //
271 // flexcan info initialisation
272 //
273 #define FLEXCAN_INFO(_l,                                                \
274                      _baseaddr,                                         \
275                      _isr_vec_mbox0,                                    \
276                      _rx_mbox_no, _rx_isr_prio,                         \
277                      _tx_mbox_no, _tx_isr_prio,                         \
278                      _boff_isr_vec, _boff_isr_prio,                     \
279                      _err_isr_vec, _err_isr_prio)                       \
280 flexcan_info _l = {                                                     \
281     (void *)( _baseaddr),                                               \
282     (_isr_vec_mbox0),                                                   \
283     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_rx_isr_prio), (_rx_mbox_no)), \
284     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_tx_isr_prio), (_tx_mbox_no)), \
285     0xFFFFFFFF,                                                         \
286     false,                                                              \
287     rxgmask       : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_GLOBAL,     \
288     rx14mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_14,         \
289     rx15mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_15,         \
290     boff_int      : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio),    \
291     err_int       : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio)       \
292 };
293
294
295 //===========================================================================
296 //                          GLOBAL DATA
297 //===========================================================================
298 //
299 // Note: two levels of macro are required to get proper expansion.
300 //
301 #define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
302 #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
303
304 //
305 // FlexCAN channel initialisation
306 //
307 FLEXCAN_INFO(flexcan_can0_info, 
308              HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
309              HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
310              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX, 
311              FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX),
312              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX, 
313              FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX),
314              HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
315              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,  
316              HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,          
317              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT);
318
319 //
320 // message box structure
321 //
322 typedef struct flexcan_mbox
323 {
324     cyg_uint8  timestamp;
325     cyg_uint8  ctrlstat;
326     cyg_uint16 id_hi;
327     cyg_uint16 id_lo;
328     cyg_uint8  data[8];
329     cyg_uint16 reserved;
330 } flexcan_mbox;
331
332 //
333 // flexcan register layout
334 //
335 typedef struct flexcan_regs
336 {
337     cyg_uint16 CANMCR;       // 0x00
338     cyg_uint16 reserved0[2]; // 0x02
339     cyg_uint8  CANCTRL0;     // 0x06
340     cyg_uint8  CANCTRL1;     // 0x07
341     cyg_uint8  PRESDIV;      // 0x08
342     cyg_uint8  CANCTRL2;     // 0x09
343     cyg_uint16 TIMER;        // 0x0A
344     cyg_uint16 reserved1[2]; // 0x0C
345     cyg_uint16 RXGMASK_HI;   // 0x10
346     cyg_uint16 RXGMASK_LO;   // 0x12
347     cyg_uint16 RX14MASK_HI;  // 0x14
348     cyg_uint16 RX14MASK_LO;  // 0x16
349     cyg_uint16 RX15MASK_HI;  // 0x18
350     cyg_uint16 RX15MASK_LO;  // 0x1A
351     cyg_uint16 reserved2[2]; // 0x1C
352     cyg_uint16 ESTAT;        // 0x20
353     cyg_uint16 IMASK;        // 0x22
354     cyg_uint16 IFLAG;        // 0x24
355     cyg_uint8  RXERRCNT;     // 0x26
356     cyg_uint8  TXERRCNT;     // 0x27
357     cyg_uint16 reserved3[44];// 0x28
358     flexcan_mbox mbox[16]; // 0x80
359 } flexcan_regs;
360
361
362 //===========================================================================
363 //                                 LOCAL DATA
364 //===========================================================================
365 static cyg_uint16 flexcan_baud_rates[] = {
366     0,      // Unused
367     10,     // 10 kbit/s
368     20,     // 20
369     50,     // 50
370     100,    // 100
371     125,    // 125
372     250,    // 250
373     500,    // 500
374     800,    // 800
375     1000,   // 1000 kbit/s
376 };
377
378
379 //===========================================================================
380 //                              PROTOTYPES
381 //===========================================================================
382 static bool        flexcan_init(struct cyg_devtab_entry* devtab_entry);
383 static Cyg_ErrNo   flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
384 static Cyg_ErrNo   flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
385 static bool        flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
386 static bool        flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
387 static void        flexcan_start_xmit(can_channel* chan);
388 static void        flexcan_stop_xmit(can_channel* chan);
389
390 //
391 // TX and RX ISRs and DSRs
392 //
393 static cyg_uint32  flexcan_mbox_rx_isr(cyg_vector_t, cyg_addrword_t);
394 static void        flexcan_mbox_rx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
395 static cyg_uint32  flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
396 static void        flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
397
398 //
399 // All other flexcan interrupt handlers
400 //
401 static cyg_uint32  flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
402 static void        flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
403 static cyg_uint32  flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
404 static void        flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
405
406
407 static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message  *pmsg, bool rtr);
408 static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_uint32 canid, cyg_uint8 ext);
409 static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
410 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext);
411 static void flexcan_start_chip(can_channel *chan);
412 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
413 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
414
415
416 CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
417                   flexcan_putmsg,
418                   flexcan_getevent,
419                   flexcan_set_config,
420                   flexcan_start_xmit,
421                   flexcan_stop_xmit
422      );
423
424
425 cyg_can_event    flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
426 cyg_can_message  flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
427
428
429 CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
430                              flexcan_lowlevel_funs,
431                              flexcan_can0_info,
432                              CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
433                              flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
434                              flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
435     );
436
437
438 DEVTAB_ENTRY(flexcan_devtab, 
439              CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
440              0,                     // Does not depend on a lower level interface
441              &cyg_io_can_devio, 
442              flexcan_init, 
443              flexcan_lookup,        // CAN driver may need initializing
444              &flexcan_can0_chan
445     );
446
447
448 //===========================================================================
449 //  Lookup the device and return its handle
450 //===========================================================================
451 static Cyg_ErrNo
452 flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
453 {
454     can_channel* chan    = (can_channel*) (*tab)->priv;
455     (chan->callbacks->can_init)(chan);
456     
457     return ENOERR;
458 }
459
460
461 //===========================================================================
462 //  Set device configuration
463 //===========================================================================
464 static Cyg_ErrNo
465 flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
466 {
467     Cyg_ErrNo     res = ENOERR;
468     
469     switch(key) 
470     {
471         case CYG_IO_SET_CONFIG_CAN_INFO:
472              {
473                  cyg_can_info_t*  config = (cyg_can_info_t*) buf;
474                  if (*len < sizeof(cyg_can_info_t)) 
475                  {
476                     return -EINVAL;
477                  }
478                  *len = sizeof(cyg_can_info_t);
479                  if (!flexcan_config(chan, config, false)) 
480                  {
481                     return -EINVAL;
482                  }
483             }
484             break;
485             
486         case CYG_IO_SET_CONFIG_CAN_RTR_BUF:
487              { 
488                  cyg_uint8          i;
489                  cyg_uint16         alloc_mask = 0x0001;
490                  flexcan_info      *info       = (flexcan_info *)chan->dev_priv;
491                  flexcan_regs      *flexcan    = (flexcan_regs *)info->base;
492                  cyg_can_rtr_buf_t *rtr_buf    = (cyg_can_rtr_buf_t*) buf;
493                  
494              
495                  if (*len != sizeof(cyg_can_rtr_buf_t)) 
496                  {
497                     return -EINVAL;
498                  }
499                  *len = sizeof(cyg_can_rtr_buf_t);
500                  
501                  //
502                  // If we need to create a new remote buffer then we check if there
503                  // is one message box free and then setup this box for remote frame
504                  // transmission
505                  //
506                  if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
507                  {
508                     rtr_buf->handle = CYGNUM_CAN_RTR_BUF_NA;
509                     for (i = 0; i < 14; ++i)
510                     {
511                         if (!(info->mbox_alloc_flags & alloc_mask))
512                         {
513                             rtr_buf->handle = i;
514                             info->mbox_alloc_flags |= alloc_mask;
515                             break;
516                         }
517                         alloc_mask <<= 1;
518                      }
519                  } // if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
520                  
521                  //
522                  // If we have a valid rtr buf handle then we can store data into 
523                  // rtr message box
524                  //
525                  if ((rtr_buf->handle >= 0) && (rtr_buf->handle < 14))
526                  {
527                      flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
528                  }
529                  else
530                  {
531                     return -EINVAL;
532                  }
533                  
534              }
535              break;
536          
537     } // switch (key)
538     
539     return res;
540 }
541
542
543 //===========================================================================
544 //  Read one event from can hardware
545 //===========================================================================
546 static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
547 {
548     flexcan_info *info           = (flexcan_info *)chan->dev_priv;
549     flexcan_regs *flexcan        = (flexcan_regs *)info->base;
550     cyg_uint8     mbox_ctrlstat;
551     bool          res            = true;
552     cyg_uint8     event_id       = *((cyg_uint8 *)pdata);
553     cyg_uint16    estat;
554         
555     //
556     // if event_id is 0 - 15 the we have a message box event - if is
557     //
558     if (event_id < FLEXCAN_ERR_EVENT)
559     {   
560         //
561         // read data from message box - during processing of this function
562         // the message box is locked and cannot receive further messages
563         //
564         flexcan_read_from_mbox(chan, event_id, pevent, &mbox_ctrlstat); 
565
566 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT    
567         if (pevent->msg.id == info->last_tx_id)
568         {
569             pevent->flags = CYGNUM_CAN_EVENT_TX;
570         }
571         else
572         {
573             pevent->flags = CYGNUM_CAN_EVENT_RX;
574         } 
575 #else // !CYGOPT_IO_CAN_TX_EVENT_SUPPORT
576         //
577         // If tx events are not supported and we received a self transmitted frame
578         // then this is not really an rx event and we return false. We rely on the
579         // fact here that two devices in network do not send the same identifier
580         //
581         if (pevent->msg.id == info->last_tx_id)    {   
582             info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
583             res = false; 
584         }
585     
586         pevent->flags = CYGNUM_CAN_EVENT_RX;
587 #endif
588     
589         //
590         // check if an overun occured in this message box
591         //
592         if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
593         {
594             pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
595         }
596     }
597     else // (event_id >= FLEXCAN_ERR_EVENT)
598     {
599         //
600         // We have an status event - check if it is an bus off interrupt or an
601         // error interrupt and provide error information to upper layer
602         //
603         HAL_READ_UINT16(&flexcan->ESTAT, estat);
604         pevent->msg.data[0] = estat & 0xFF;
605         pevent->msg.data[1] = (estat >> 8) & 0xFF; 
606         HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data[2]);
607         HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data[3]);
608         switch (event_id)
609         {
610             case FLEXCAN_ERR_EVENT :
611                  //
612                  // indicate error passive event and provide content of estat register
613                  // for a more precise error information
614                  //
615                  if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
616                  {
617                     pevent->flags = CYGNUM_CAN_EVENT_ERR_PASSIVE;
618                  }
619                  //
620                  // If we are not in error passive state then we check if the
621                  // error counters reached the warning level
622                  //
623                  else
624                  {               
625                      //
626                      // indicate tx error counter warning level reached
627                      //
628                      if (estat & FLEXCAN_ESTAT_TXWARN)
629                      {
630                          pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
631                      }
632                  
633                      //
634                      // indicate rx error counter warning level reached
635                      //
636                      if (estat & FLEXCAN_ESTAT_RXWARN)
637                      {
638                          pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
639                      }
640                  }
641                  break;
642                  
643             case FLEXCAN_BUSOFF_EVENT:
644                  pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
645                  break;
646         } // switch (event_id)
647     }
648
649     return res;
650 }
651
652
653 //===========================================================================
654 // Send one CAN message to CAN hardware
655 //===========================================================================
656 static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
657 {
658     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
659     flexcan_regs *flexcan = (flexcan_regs *)info->base;
660     cyg_uint8        mbox = *((cyg_uint8 *)pdata);
661     cyg_uint16       iflag;
662    
663     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
664     
665     //
666     // check if device is busy sending a message
667     //
668     if (info->tx_busy)
669     {
670         //
671         // if devise is busy and the interrupt flag is set, then we know
672         // that device is not busy any longer - if more message boxes are
673         // used for transmitting then tx_busy should be part of a message box
674         // structure to keep track of the state of different message boxes
675         //
676         if (iflag & (0x0001 << mbox))
677         {
678             HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
679         }
680         else
681         {
682             return false;
683         }
684     }
685     
686     info->tx_busy    = true;     // mark transmitter as busy
687     info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames
688     flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false);
689     
690     return true;
691 }
692
693
694 //===========================================================================
695 // Flexcan start xmit
696 //===========================================================================
697 static void flexcan_start_xmit(can_channel* chan)
698 {
699     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
700     flexcan_regs *flexcan = (flexcan_regs *)info->base;
701     cyg_uint16    imask;
702     CYG_INTERRUPT_STATE     saved_state;
703
704     HAL_DISABLE_INTERRUPTS(saved_state);
705     
706     //
707     // Now enable message box 15 interrupts
708     //
709     HAL_READ_UINT16(&flexcan->IMASK, imask);
710     HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << info->tx_mbox.num));
711     
712     //
713     // kick transmitter
714     //
715     chan->callbacks->xmt_msg(chan, &info->tx_mbox.num);  // Kick transmitter (if necessary)
716     
717     HAL_RESTORE_INTERRUPTS(saved_state);
718 }
719
720
721 //===========================================================================
722 // Flexcan start xmit
723 //===========================================================================
724 static void flexcan_stop_xmit(can_channel* chan)
725 {
726     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
727     flexcan_regs *flexcan = (flexcan_regs *)info->base;
728     cyg_uint16    imask;
729     CYG_INTERRUPT_STATE     saved_state;
730
731     HAL_DISABLE_INTERRUPTS(saved_state);
732     
733     //
734     // Now disable message box 15 interrupts
735     //
736     HAL_READ_UINT16(&flexcan->IMASK, imask);
737     HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << info->tx_mbox.num));
738
739     HAL_RESTORE_INTERRUPTS(saved_state);
740 }
741
742
743 //===========================================================================
744 // Configure flexcan channel
745 //===========================================================================
746 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
747 {
748     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
749     flexcan_regs *flexcan = (flexcan_regs *)info->base;
750     cyg_uint16    tmp16;
751     cyg_uint8     tmp8;
752     cyg_uint8     i;
753     
754     if (init)
755     {
756 #if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
757         if (info == &flexcan_can0_info) {
758             HAL_MCF52xx_FLEXCAN0_PROC_INIT();
759         }
760 #endif
761         
762         //
763         // Issue a reset in order to go into halt mode. The reset will set the
764         // the halt bit in mcr
765         //
766         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
767         tmp16 &= ~FLEXCAN_MCR_FRZ;
768         HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
769         tmp16 |= FLEXCAN_MCR_SOFTRST;
770         HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
771         HAL_DELAY_US(10);
772     
773         //
774         // Check reset status
775         //
776         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
777         if (tmp16 & FLEXCAN_MCR_SOFTRST)
778         {
779             return false;
780         }
781     
782         //
783         // Initialize the transmit and receive pin modes
784         //
785         HAL_WRITE_UINT8(&flexcan->CANCTRL0 , (FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT  
786                                             | FLEXCAN_CTRL0_RXMODE_0_DOMINANT)
787                                             & ~FLEXCAN_CTRL0_BOFFMSK
788                                             & ~FLEXCAN_CTRL0_ERRMASK);
789                                             
790         //
791         // setup message box acceptance filter
792         //
793         flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  info->rxgmask, 0);
794         flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, info->rx14mask, 0);
795         flexcan_set_acceptance_mask(&flexcan->RX15MASK_HI, info->rx15mask, 0);                                          
796     } // if (init)
797     
798     //
799     // stop chip
800     //
801     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
802     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);  
803     
804     //
805     // deactivate all message buffers - this is mandatory for configuration
806     // of message buffers
807     //
808     for (i = 0; i < 16; ++i)
809     {
810         HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
811     }
812     //
813     // mask all interrupts
814     //
815     HAL_WRITE_UINT16(&flexcan->IMASK, 0x0000);
816     HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
817     HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
818                       
819     flexcan_set_baud(chan, config->baud);
820     
821     //
822     // setup bus arbitration mode - the LBUF bit defines the 
823     // transmit-first scheme 0 = message buffer with lowest ID
824     // 1 = message buffer with lowest number. We use lowest ID here
825     //
826     HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
827     HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));
828         
829     info->mbox_alloc_flags = 0; // no buffers used yet
830     
831     //
832     // Message box 14 is our receiv message box. We configure it for
833     // reception of any message
834     //
835     flexcan_cfg_mbox_rx(&flexcan->mbox[info->rx_mbox.num], 0x100, 0);
836     flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, 0, 0);
837     info->mbox_alloc_flags |= (0x0001 << info->rx_mbox.num); // mark rx mbox flag as used
838     info->mbox_alloc_flags |= (0x0001 << info->tx_mbox.num); // mark tx mbox flag as used
839     
840     //
841     // enable the rx interrupt for mbox 0 (tx interrupt are enabled in start xmit)
842     // bus off interrupt and error interrupt
843     //
844     HAL_WRITE_UINT16(&flexcan->IMASK, (0x0001 << info->rx_mbox.num));
845     HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
846     HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
847     
848     //
849     // now we can start the chip
850     //
851     flexcan_start_chip(chan);
852     
853     //
854     // store new config values
855     //
856     if (config != &chan->config) 
857     {
858         chan->config = *config;
859     }
860     
861     return true;
862 }
863
864 //===========================================================================
865 //                           CAN INIT
866 //
867 /// First initialisation and reset of CAN modul.
868 //===========================================================================
869 static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
870 {
871     can_channel  *chan    = (can_channel*)devtab_entry->priv;
872     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
873
874     if (!flexcan_config(chan, &chan->config, true))
875     {
876         return false;
877     }
878     
879     //
880     // prepare message box interrupt for message box 0 - the rx message box
881     //
882     cyg_drv_interrupt_create(info->rx_mbox.isr_vec,
883                              info->rx_mbox.isr_priority,
884                              (cyg_addrword_t) chan,
885                              &flexcan_mbox_rx_isr,
886                              &flexcan_mbox_rx_dsr,
887                              &(info->rx_mbox.interrupt_handle),
888                              &(info->rx_mbox.interrupt));
889     cyg_drv_interrupt_attach(info->rx_mbox.interrupt_handle);
890     cyg_drv_interrupt_unmask(info->rx_mbox.isr_vec);
891     
892     //
893     // prepare message box interrupt for message box 15 - the tx message box
894     //
895     cyg_drv_interrupt_create(info->tx_mbox.isr_vec,
896                              info->tx_mbox.isr_priority,
897                              (cyg_addrword_t) chan,
898                              &flexcan_mbox_tx_isr,
899                              &flexcan_mbox_tx_dsr,
900                              &(info->tx_mbox.interrupt_handle),
901                              &(info->tx_mbox.interrupt));
902     cyg_drv_interrupt_attach(info->tx_mbox.interrupt_handle);
903     cyg_drv_interrupt_unmask(info->tx_mbox.isr_vec);
904     
905     //
906     // prepare error interrupt
907     //
908     cyg_drv_interrupt_create(info->err_int.isr_vec,
909                              info->err_int.isr_priority,
910                              (cyg_addrword_t) chan,
911                              &flexcan_err_isr,
912                              &flexcan_err_dsr,
913                              &(info->err_int.interrupt_handle),
914                              &(info->err_int.interrupt));
915     cyg_drv_interrupt_attach(info->err_int.interrupt_handle);
916     cyg_drv_interrupt_unmask(info->err_int.isr_vec);
917     
918     //
919     // prepare busoff interrupt
920     //
921     cyg_drv_interrupt_create(info->boff_int.isr_vec,
922                              info->boff_int.isr_priority,
923                              (cyg_addrword_t) chan,
924                              &flexcan_busoff_isr,
925                              &flexcan_busoff_dsr,
926                              &(info->boff_int.interrupt_handle),
927                              &(info->boff_int.interrupt));
928     cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
929     cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
930         
931     return true;
932 }
933
934
935 //===========================================================================
936 // Flexcan error interrupt handler
937 //===========================================================================
938 static cyg_uint32  flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
939 {
940     can_channel  *chan    = (can_channel *)data;
941     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
942     flexcan_regs *flexcan = (flexcan_regs *)info->base;
943     cyg_uint8     ctrl0;
944     cyg_uint16    estat;
945     
946     //
947     // first we disable error interrupts - DSR will reenable it later
948     //
949     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
950     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
951     
952     //
953     // for clearing the interrupt we first read the flag register as 1
954     // and then write it as 1 (and not as zero like the manual stated)
955     // we clear only the flag of this interrupt and leave all other
956     // message box interrupts untouched
957     //
958     HAL_READ_UINT16(&flexcan->ESTAT, estat);
959     HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT); 
960     
961     //
962     // On the mcf5272 there is no need to acknowledge internal
963     // interrupts, only external ones.
964     // cyg_drv_interrupt_acknowledge(vec);
965     //
966     return CYG_ISR_CALL_DSR;
967 }
968
969
970 //===========================================================================
971 // DSR for all interrupts that are no message box interrupts
972 //===========================================================================
973 static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
974 {
975     can_channel  *chan     = (can_channel *)data;
976     flexcan_info *info     = (flexcan_info *)chan->dev_priv;
977     flexcan_regs *flexcan  = (flexcan_regs *)info->base;
978     cyg_uint8     ctrl0;
979     cyg_uint8     event_id = FLEXCAN_ERR_EVENT;
980
981     //
982     // signal CAN event to generic IO CAN driver - it will do any further 
983     // processing
984     //            
985     chan->callbacks->rcv_event(chan, &event_id);
986     
987     //
988     // reenable bus off interrupts
989     //
990     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
991     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
992 }
993
994
995 //===========================================================================
996 // Bus off interrupt handler
997 //===========================================================================
998 static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
999 {
1000     can_channel  *chan    = (can_channel *)data;
1001     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1002     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1003     cyg_uint8     ctrl0;
1004     cyg_uint16    estat;
1005     
1006     //
1007     // first we disable bus off interrupts - DSR will reenable it later
1008     //
1009     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1010     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
1011     
1012     //
1013     // for clearing the interrupt we first read the flag register as 1
1014     // and then write it as 1 (and not as zero like the manual stated)
1015     // we clear only the flag of this interrupt and leave all other
1016     // message box interrupts untouched
1017     //
1018     HAL_READ_UINT16(&flexcan->ESTAT, estat);
1019     HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);  
1020     
1021     //
1022     // On the mcf5272 there is no need to acknowledge internal
1023     // interrupts, only external ones.
1024     // cyg_drv_interrupt_acknowledge(vec);
1025     //
1026     return CYG_ISR_CALL_DSR;
1027 }
1028
1029
1030 //===========================================================================
1031 // DSR for all interrupts that are no message box interrupts
1032 //===========================================================================
1033 static void flexcan_busoff_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1034 {
1035     can_channel  *chan     = (can_channel *)data;
1036     flexcan_info *info     = (flexcan_info *)chan->dev_priv;
1037     flexcan_regs *flexcan  = (flexcan_regs *)info->base;
1038     cyg_uint8     ctrl0;
1039     cyg_uint8     event_id = FLEXCAN_BUSOFF_EVENT;
1040
1041     //
1042     // signal CAN event to generic IO CAN driver - it will do any further 
1043     // processing
1044     //            
1045     chan->callbacks->rcv_event(chan, &event_id);
1046     
1047     //
1048     // reenable bus off interrupts
1049     //
1050     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1051     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);  
1052 }
1053
1054
1055 //===========================================================================
1056 // Flexcan message box isr
1057 //===========================================================================
1058 static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
1059 {
1060     can_channel  *chan    = (can_channel *)data;
1061     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1062     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1063     cyg_uint16    iflag;
1064     cyg_uint16    imask;
1065     
1066     //
1067     // number of message box can be calculated from vector that cause
1068     // interrupt - we pass this message box number as additional data to the
1069     // callback because it is required in the receive event function later
1070     //
1071     cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
1072     
1073     //
1074     // first we disable interrupts of this message box - the DSR will
1075     // reenable it later
1076     //
1077     HAL_READ_UINT16(&flexcan->IMASK, imask);
1078     HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
1079     
1080     //
1081     // for clearing the interrupt we first read the flag register as 1
1082     // and then write it as 1 (and not as zero like the manual stated)
1083     // we clear only the flag of this interrupt and leave all other
1084     // message box interrupts untouched
1085     //
1086     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1087     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));    
1088     
1089     //
1090     // On the mcf5272 there is no need to acknowledge internal
1091     // interrupts, only external ones.
1092     // cyg_drv_interrupt_acknowledge(vec);
1093     //
1094     return CYG_ISR_CALL_DSR;
1095 }
1096
1097
1098 //===========================================================================
1099 // Flexcan message box dsr
1100 //===========================================================================
1101 static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1102 {
1103     can_channel  *chan    = (can_channel *)data;
1104     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1105     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1106     cyg_uint16    imask;
1107     
1108     //
1109     // number of message box can be calculated from vector that caused
1110     // interrupt - we pass this message box number as additional data to the
1111     // callback
1112     //
1113     cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
1114     
1115     //
1116     // signal CAN event to generic IO CAN driver - it will do any further 
1117     // processing
1118     //            
1119     chan->callbacks->rcv_event(chan, &mbox);
1120     
1121     //
1122     // reenable interrupts for the message box that caused the DSR to run
1123     //
1124     HAL_READ_UINT16(&flexcan->IMASK, imask);
1125     HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox)); 
1126 }
1127
1128 //===========================================================================
1129 // Flexcan message box isr
1130 //===========================================================================
1131 static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
1132 {
1133     can_channel  *chan    = (can_channel *)data;
1134     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1135     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1136     cyg_uint16    iflag;
1137     cyg_uint16    imask;
1138     
1139     // number of message box can be calculated from vector that cause
1140     // interrupt - we pass this message box number as additional data to the
1141     // callback
1142     //
1143     cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1144     
1145     //
1146     // the first thing we do here is to disable this message box. we do this
1147     // because if we just sent a remote transmission request with this message
1148     // box then the FLEXCAN modul will automatically set up this message box
1149     // for reception of the requested data frame. But we won't receive messages
1150     // with the TX message box and deactivate it here immediatelly.
1151     // 
1152     HAL_WRITE_UINT8(&flexcan->mbox[mbox].ctrlstat, MBOX_TXCODE_NOT_READY);   
1153     
1154     //
1155     // first we disable interrupts of this message box - the DSR will
1156     // reenable it later
1157     //
1158     HAL_READ_UINT16(&flexcan->IMASK, imask);
1159     HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
1160     
1161     //
1162     // for clearing the interrupt we first read the flag register as 1
1163     // and then write it as 1 (and not as zero like the manual stated)
1164     // we clear only the flag of this interrupt and leave all other
1165     // message box interrupts untouched
1166     //
1167     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1168     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); 
1169     info->tx_busy = false;   
1170     
1171     //
1172     // On the mcf5272 there is no need to acknowledge internal
1173     // interrupts, only external ones.
1174     // cyg_drv_interrupt_acknowledge(vec);
1175     //
1176     return CYG_ISR_CALL_DSR;
1177 }
1178
1179
1180 //===========================================================================
1181 // Flexcan message box dsr
1182 //===========================================================================
1183 static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1184 {
1185     can_channel  *chan    = (can_channel *)data;
1186     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1187     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1188     cyg_uint16    imask;
1189     
1190     //
1191     // number of message box can be calculated from vector that caused
1192     // interrupt - we pass this message box number as additional data to the
1193     // callback
1194     //
1195     cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
1196     
1197     //
1198     // send next message 
1199     //            
1200     chan->callbacks->xmt_msg(chan, &mbox);
1201     
1202     //
1203     // reenable interrupts for the message box that caused the DSR to run
1204     //
1205     HAL_READ_UINT16(&flexcan->IMASK, imask);
1206     HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox));
1207 }
1208
1209
1210 //===========================================================================
1211 //                     START FLEXCAN MODUL
1212 //===========================================================================
1213 static void flexcan_start_chip(can_channel *chan)
1214 {
1215     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1216     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1217     
1218     cyg_uint16 tmp16;
1219     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
1220     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 
1221                  & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
1222 }
1223
1224
1225 //===========================================================================
1226 //                      SET ACCEPTANCE MASK
1227 //===========================================================================
1228 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext)
1229 {
1230     cyg_uint16 id;
1231     //
1232     // 32 bit access to RXMASK filters is broken so we use  16 Bit
1233     // access here
1234     //
1235     if (ext != 0)
1236     {
1237         id  = ((mask >> 13) & 0xFFE0);       // set mask bits 18 - 28
1238         id |= ((mask >> 15) & 0x7);          // set mask bits 15 -17
1239         HAL_WRITE_UINT16(&rxmask_reg[0], id);
1240         
1241         id = (mask << 1) & 0xFFFE;
1242         HAL_WRITE_UINT16(&rxmask_reg[1], id);
1243     }
1244     else
1245     {
1246         id = ((mask << 5) & 0xFFE0); 
1247         HAL_WRITE_UINT16(&rxmask_reg[0], id);
1248         HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);  
1249     }
1250     
1251 }
1252
1253
1254
1255 //===========================================================================
1256 //                 CONFIGURE MESSAGE BOX FOR TRANSMISSION
1257 //===========================================================================
1258 static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
1259                                 cyg_can_message  *pmsg,
1260                                 bool              rtr)
1261 {
1262     cyg_uint16 id;
1263   
1264     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY); 
1265     
1266     if (pmsg->ext != 0)
1267     { 
1268         id  = ((pmsg->id >> 13) & 0xFFE0);   // setup id bits 18 - 28
1269         id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
1270         id |= ((pmsg->id >> 15) & 0x7);      // set id bits 15 - 17
1271         HAL_WRITE_UINT16(&pmbox->id_hi, id);
1272         
1273         id = ((pmsg->id << 1) & 0xFFFE);
1274         
1275         if (pmsg->rtr)
1276         {
1277             id |= MBOX_CFG_RTR_EXT;
1278         }   
1279         
1280         HAL_WRITE_UINT16(&pmbox->id_lo, id);
1281     }   
1282     else
1283     {
1284         id = ((pmsg->id << 5) & 0xFFE0);
1285         if (pmsg->rtr)
1286         {
1287             id |= MBOX_CFG_RTR_STD;           // set rtr bit for standard ID
1288         }
1289         HAL_WRITE_UINT16(&pmbox->id_hi, id);
1290         HAL_WRITE_UINT16(&pmbox->id_lo, 0);
1291     }
1292     
1293     pmsg->dlc %= 9; // limit data length to 8 bytes
1294     
1295     //
1296     // Now copy data bytes into buffer and start transmission
1297     //
1298     HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); 
1299     
1300     if (rtr)
1301     {
1302         HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
1303     }
1304     else
1305     {
1306         HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
1307     }
1308     
1309     return true;
1310 }
1311
1312
1313
1314 //===========================================================================
1315 //              CONFIGURE MESSAGE BOX FOR RECEPTION OF FRAMES
1316 //===========================================================================
1317 static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox,
1318                                 cyg_uint32    canid,
1319                                 cyg_uint8     ext)
1320 {
1321     cyg_uint16 id;
1322     
1323     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE); 
1324     
1325     if (ext != 0)
1326     { 
1327         id  = ((canid >> 13) & 0xFFE0);      // setup id bits 18 - 28
1328         id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
1329         id |= ((canid >> 15) & 0x7);         // set id bits 15 - 17
1330         HAL_WRITE_UINT16(&pmbox->id_hi, id);  // write ID high
1331         
1332         id = ((canid << 1) & 0xFFFE);
1333         
1334         HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
1335     }   
1336     else
1337     {
1338         id = ((canid << 5) & 0xFFE0);
1339
1340         HAL_WRITE_UINT16(&pmbox->id_hi, id);
1341         HAL_WRITE_UINT16(&pmbox->id_lo, 0);
1342     }
1343     
1344     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
1345 }
1346
1347
1348 //===========================================================================
1349 //                       READ DATA FROM MESSAGE BOX
1350 //==========================================================================
1351 static void flexcan_read_from_mbox(can_channel  *chan,
1352                             cyg_uint8            mbox,
1353                             cyg_can_event       *pevent,
1354                             cyg_uint8           *ctrlstat)
1355 {
1356     flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
1357     flexcan_regs    *flexcan = (flexcan_regs *)info->base;
1358     flexcan_mbox    *pmbox   = &flexcan->mbox[mbox];
1359     cyg_can_message *pmsg    = &pevent->msg;
1360     cyg_uint16       id;
1361     cyg_uint8        i;
1362     
1363     HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
1364     
1365     //
1366     // If message buffer is busy then it is now beeing filled with a new message
1367     // This condition will be cleared within 20 cycles - wi simply do a 20 us
1368     // delay here, that should be enougth
1369     //
1370     if (*ctrlstat & MBOX_RXCODE_BUSY)
1371     {
1372         HAL_DELAY_US(20);
1373     }
1374     
1375     pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
1376     pmsg->rtr = 0;
1377     
1378     HAL_READ_UINT16(&pmbox->id_hi, id);         // read ID high
1379     
1380     if (id & MBOX_CFG_IDE)
1381     {
1382         pmsg->ext = 1;
1383         pmsg->id  = (id & 0xFFE0) << 13;
1384         
1385         HAL_READ_UINT16(&pmbox->id_lo, id);
1386         pmsg->id |= (id & 0xFFFE) >> 1;
1387     }
1388     else
1389     {
1390         pmsg->ext = 0;
1391         pmsg->id  = (id & 0xFFE0) >> 5;
1392     }
1393     
1394     //
1395     // now finally copy data
1396     //
1397     HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
1398        
1399     //
1400     // now zero out the remaining bytes in can message in order
1401     // to deliver a defined state
1402     //
1403     for (i = pmsg->dlc; i < 8; ++i)
1404     {
1405         pmsg->data[i] = 0;
1406     }
1407   
1408     //
1409     // now mark this mbox as empty and read the free running timer
1410     // to unlock this mbox
1411     //
1412     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
1413     HAL_READ_UINT16(&flexcan->TIMER, id);
1414 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP    
1415     pevent->timestamp = id;
1416 #endif
1417 }
1418
1419
1420 //===========================================================================
1421 //                           INIT CAN BAUD RATE
1422 //===========================================================================
1423 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
1424 {
1425     flexcan_info             *info = (flexcan_info *)chan->dev_priv;
1426     flexcan_regs             *flexcan = (flexcan_regs *)info->base;
1427     cyg_uint16                mcr_bck;
1428     cyg_uint8                 tmp8;
1429     cyg_uint8                 presdiv;
1430     cyg_uint8                 propseg;
1431     cyg_uint8                 pseg1_2;
1432     cyg_uint16                baudrate = flexcan_baud_rates[baud];
1433     
1434     //
1435     // Get bit timings from HAL because bit timings depend on sysclock
1436     //
1437     HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
1438     
1439     //
1440     // return false if baudrate is not supported
1441     //
1442     if (0 == baudrate)
1443     {
1444         return false;
1445     }
1446     
1447     //
1448     // For setting the bit timings we have to stop the flexcan modul
1449     //
1450     HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
1451     HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
1452     
1453     //
1454     // now we setup bit timings
1455     //
1456     HAL_WRITE_UINT8(&flexcan->PRESDIV, presdiv);
1457     HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
1458     HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & 0xF8) | propseg); 
1459     HAL_READ_UINT8(&flexcan->CANCTRL2, tmp8);
1460     HAL_WRITE_UINT8(&flexcan->CANCTRL2, (tmp8 & 0xC0) | pseg1_2); 
1461     
1462     //
1463     // Now restore the previous state - if the modul was started then
1464     // it will no be started again, if it was stopped, then it remains stopped
1465     //
1466     HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
1467     
1468     return true;
1469 }
1470
1471 //---------------------------------------------------------------------------
1472 // end of can_mcf_flexcan.c
1473