More updates in the C_CAN support, but locking not reworked still.
[lincan.git] / lincan / src / c_can_irq.c
1 /* c_can_irq.c - Hynix HMS30c7202 ARM IRQ handling code
2  * Linux CAN-bus device driver.
3  * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de
4  * Based on code from Arnaud Westenberg email:arnaud@wanadoo.nl
5  * and Ake Hedman, eurosource, akhe@eurosource.se
6  * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
7  * email:pisa@cmp.felk.cvut.cz
8  * This software is released under the GPL-License.
9  * Version lincan-0.3  17 Jun 2004
10  */
11
12 #include "../include/can.h"
13 #include "../include/can_sysdep.h"
14 #include "../include/main.h"
15 #include "../include/c_can.h"
16
17 union c_can_data {
18         unsigned short wdata[4];
19         unsigned char bdata[8];
20 };
21
22 // prototypes
23 inline void c_can_irq_read_handler(struct canchip_t *pchip, int idxobj,
24                                    u32 msgid);
25
26 inline void c_can_irq_write_handler(struct canchip_t *pchip, int idxobj);
27
28 void c_can_irq_rtr_handler(struct canchip_t *pchip, int idxobj, u32 msgid);
29
30 u16 readMaskCM = IFXCM_ARB | IFXCM_CNTRL | IFXCM_CLRINTPND
31     | IFXCM_TRND | IFXCM_DA | IFXCM_DB;
32
33 u16 msgLstReadMaskCM = IFXCM_CNTRL;
34 u16 msgLstWriteMaskCM = IFXCM_CNTRL | IFXCM_WRRD;
35
36 ///////////////////////////////////////////////////////////////////////////////
37 // c_can_irq_write_handler
38 //
39 // Send a message from the output fifo ( if any ).
40 //
41
42 inline void c_can_irq_write_handler(struct canchip_t *pchip, int idxobj)
43 {
44         int cmd;
45         struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
46
47         DEBUGMSG("(c%dm%d)calling c_can_irq_write_handler(...)\n",
48                  pchip->chip_idx, pmsgobj->object);
49
50         if (pmsgobj->tx_slot) {
51                 /* Do local transmitted message distribution if enabled */
52                 if (processlocal) {
53                         /* fill CAN message timestamp */
54                         can_filltimestamp(&pmsgobj->tx_slot->msg.timestamp);
55
56                         pmsgobj->tx_slot->msg.flags |= MSG_LOCAL;
57                         canque_filter_msg2edges(pmsgobj->qends,
58                                                 &pmsgobj->tx_slot->msg);
59                 }
60                 /* Free transmitted slot */
61                 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge,
62                                     pmsgobj->tx_slot);
63                 pmsgobj->tx_slot = NULL;
64         }
65         // Get ready to send next message
66         spin_lock(&c_can_spwlock);
67
68         cmd =
69             canque_test_outslot(pmsgobj->qends, &pmsgobj->tx_qedge,
70                                 &pmsgobj->tx_slot);
71         if (cmd < 0) {
72                 DEBUGMSG("(c%dm%d)Nothin to write\n",
73                          pchip->chip_idx, pmsgobj->object);
74                 spin_unlock(&c_can_spwlock);
75                 return;
76         }
77         // Send the message
78         if (pchip->chipspecops->
79             send_msg(pchip, pmsgobj, &pmsgobj->tx_slot->msg)) {
80                 pmsgobj->ret = -1;
81                 canque_notify_inends(pmsgobj->tx_qedge,
82                                      CANQUEUE_NOTIFY_ERRTX_SEND);
83                 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge,
84                                     pmsgobj->tx_slot);
85                 pmsgobj->tx_slot = NULL;
86                 spin_unlock(&c_can_spwlock);
87                 DEBUGMSG("(c%dm%d)c_can_irq_handler: Unable to send message\n",
88                          pchip->chip_idx, pmsgobj->object);
89                 return;
90         } else {
91                 // Another message sent
92 #ifdef CAN_WITH_STATISTICS
93                 pchip->stat.cntTxPkt++;
94                 pchip->stat.cntTxData += pmsgobj->tx_slot->length;
95 #endif /*CAN_WITH_STATISTICS */
96         }
97         spin_unlock(&c_can_spwlock);
98
99         // Wake up any waiting writer
100         return;
101 }
102
103 ///////////////////////////////////////////////////////////////////////////////
104 // c_can_irq_read_handler
105 //
106 // Message received form the line. Write it in the input fifo->
107 //
108
109 inline void c_can_irq_read_handler(struct canchip_t *pchip,
110                                    int idxobj, u32 msgid)
111 {
112         int i = 0;
113         u16 bDataAvail = 1;
114         u16 msgCntlReg = 0;
115         union c_can_data readData;
116         struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
117
118         DEBUGMSG("(c%dm%d)calling c_can_irq_read_handler(...)\n",
119                  pchip->chip_idx, pmsgobj->object);
120
121         while (bDataAvail) {
122
123 #ifdef CAN_WITH_STATISTICS
124                 pchip->stat.cntRxFifoOvr++;
125 #endif /*CAN_WITH_STATISTICS */
126                 // Message length
127                 msgCntlReg = c_can_read_reg_w(pchip, CCIF1DMC);
128
129                 pmsgobj->rx_msg.length = msgCntlReg & 0x000F;
130
131                 // Message id
132                 pmsgobj->rx_msg.id = (u32) msgid;
133
134                 // Fetch message bytes
135                 if (pmsgobj->rx_msg.length > 0)
136                         readData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
137                 if (pmsgobj->rx_msg.length > 2)
138                         readData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
139                 if (pmsgobj->rx_msg.length > 4)
140                         readData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
141                 if (pmsgobj->rx_msg.length > 6)
142                         readData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
143
144                 for (i = 0; i < pmsgobj->rx_msg.length; i++) {
145                         pmsgobj->rx_msg.data[i] = readData.bdata[i];
146                 }
147                 DEBUGMSG("(c%dm%d)Received Message:\n",
148                          pchip->chip_idx, pmsgobj->object);
149                 DEBUGMSG(" id = %ld\n", pmsgobj->rx_msg.id);
150                 DEBUGMSG(" length = %d\n", pmsgobj->rx_msg.length);
151                 for (i = 0; i < pmsgobj->rx_msg.length; i++)
152                         DEBUGMSG(" data[%d] = 0x%.2x\n", i,
153                                  pmsgobj->rx_msg.data[i]);
154
155                 /* fill CAN message timestamp */
156                 can_filltimestamp(&pmsgobj->rx_msg.timestamp);
157
158                 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->rx_msg);
159
160 #ifdef CAN_WITH_STATISTICS
161                 // Another received packet
162                 pchip->stat.cntRxPkt++;
163
164                 // Add databytes read to statistics block
165                 pchip->stat.cntRxData += pmsgobj->rx_msg.length;
166 #endif /*CAN_WITH_STATISTICS */
167
168                 // Check if new data arrived
169                 if (c_can_if1_busycheck(pchip)) ;
170                 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
171                 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
172                 if (c_can_if1_busycheck(pchip)) ;
173                 if (!((bDataAvail = c_can_read_reg_w(pchip, CCIF1DMC)) &
174                       IFXMC_NEWDAT)) {
175                         break;
176                 }
177
178                 if (bDataAvail & IFXMC_MSGLST) {
179                         CANMSG("(c%dm%d)c-can fifo full: Message lost!\n",
180                                pchip->chip_idx, pmsgobj->object);
181                 }
182
183         }
184         // while
185 }
186
187 ///////////////////////////////////////////////////////////////////////////////
188 // c_can_irq_update_filter
189 //
190 // update acceptance filter for given object.
191 //
192
193 void c_can_irq_update_filter(struct canchip_t *pchip, struct msgobj_t *obj)
194 {
195         struct canfilt_t filt;
196
197         if(canqueue_ends_filt_conjuction(obj->qends, &filt)) {
198                 obj->rx_preconfig_id=filt.id;
199
200                 if (filt.flags&MSG_EXT)
201                         can_msgobj_set_fl(obj,RX_MODE_EXT);
202                 else
203                         can_msgobj_clear_fl(obj,RX_MODE_EXT);
204
205                 c_can_mask(obj, filt.mask, 0);
206
207                 c_can_pre_read_config(pchip, obj);
208
209                 CANMSG("c_can_irq_update_filter: obj #%d\n",obj->object);
210         }
211 }
212
213 ///////////////////////////////////////////////////////////////////////////////
214 // c_can_irq_sync_activities
215 //
216 // ensure, that not requests for object activities are serialized.
217 //
218
219 void c_can_irq_sync_activities(struct canchip_t *pchip, struct msgobj_t *obj)
220 {
221         while (!can_msgobj_test_and_set_fl(obj, TX_LOCK)) {
222
223                 if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
224                         int cctreqx;
225                         int idxobj = obj->object-1;
226                         
227                         if(idxobj<0) {
228                                 DEBUGMSG("c_can_irq_sync_activities wrong idxobj\n");
229                                 break;
230                         }
231
232                         if(idxobj < 16)
233                                 cctreqx = c_can_read_reg_w(pchip, CCTREQ1);
234                         else
235                                 cctreqx = c_can_read_reg_w(pchip, CCTREQ2);
236
237                         if (!(cctreqx & (1 << (idxobj & 0xf)))) {
238                                 can_msgobj_clear_fl(obj, TX_REQUEST);
239                                 c_can_irq_write_handler(pchip, idxobj);
240                         }
241                 }
242
243                 if(!obj->tx_slot) {
244                         if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
245                                 c_can_irq_update_filter(pchip, obj);
246                         }
247                 }
248
249                 can_msgobj_clear_fl(obj, TX_LOCK);
250
251                 mb();
252
253                 if (can_msgobj_test_fl(obj, TX_REQUEST))
254                         continue;
255                 if (can_msgobj_test_fl(obj, FILTCH_REQUEST) && !obj->tx_slot)
256                         continue;
257                 break;
258         }
259 }
260
261 ///////////////////////////////////////////////////////////////////////////////
262 // c_can_irq_handler
263 //
264
265 int c_can_irq_handler(int irq, struct canchip_t *pchip)
266 {
267         struct rtr_id *rtr_search = hardware_p->rtr_queue;
268         u16 chip_status;
269         int id0 = 0, id1 = 0;
270         u16 errcount = 0;
271         u16 irqreg = 0;
272         u32 msgid = 0;
273         u16 tempCntlReg = 0;
274
275         irqreg = c_can_read_reg_w(pchip, CCINTR);
276
277         if (!irqreg) {
278                 DEBUGMSG("\n(c%d)IRQ handler: addr=%.8lx spurious interrupt\n",
279                          pchip->chip_idx,
280                          (long)(pchip-> /*v */ chip_base_addr /* + CCSR */ ));
281                 return CANCHIP_IRQ_NONE;
282         }
283
284         DEBUGMSG("\n(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x\n",
285                  pchip->chip_idx,
286                  (long)(pchip-> /*v */ chip_base_addr /* + CCSR */ ),
287                  irqreg);
288
289 #ifdef REGDUMP
290         c_can_registerdump(pchip);
291 #endif
292
293         while (irqreg) {
294                 // Handle change in status register
295
296                 if (irqreg == INT_STAT) {
297                         chip_status = c_can_read_reg_w(pchip, CCSR);
298                         DEBUGMSG("(c%d)Status register: 0x%x\n",
299                                  pchip->chip_idx, chip_status);
300
301                         if (chip_status & SR_EWARN) {
302                                 // There is an abnormal # of errors
303 #ifdef CAN_WITH_STATISTICS
304                                 pchip->stat.cntWarnings++;
305 #endif /*CAN_WITH_STATISTICS */
306                                 errcount = c_can_read_reg_w(pchip, CCEC);
307                                 DEBUGMSG
308                                     ("(c%d)stat: c_can_irq_handler: Abnormal number of Errors Warning\n"
309                                      "       txErr=%d, rxErr=%d\n",
310                                      pchip->chip_idx, (errcount & 0x00ff),
311                                      ((errcount & 0x7f00) >> 8));
312
313                                 /*
314                                    // this code deactivates the chip if the transmiterrorcounter grew above 127
315                                    if ((pchip->stat.cntWarnings > 100) && ((errcount&0x00ff) > 127))
316                                    {
317                                    CANMSG("(c%d)to much Errornumber warnings (>100), deactivating chip",
318                                    pchip->chip_idx);
319                                    pchip->config_irqs(pchip, 0);
320                                    pchip->enable_configuration(pchip);
321                                    pchip->clear_objects(pchip);
322                                    pchip->flags &= ~CHANNEL_CONFIGURED;
323                                    return;
324                                    } */
325                         }
326
327                         if (chip_status & SR_EPASS) {
328                                 // There is an abnormal # of errors
329 #ifdef CAN_WITH_STATISTICS
330                                 pchip->stat.cntErrPassive++;
331 #endif /*CAN_WITH_STATISTICS */
332                                 DEBUGMSG
333                                     ("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
334                                      pchip->chip_idx);
335                         }
336
337                         if (chip_status & SR_BOFF) {
338                                 // We have a bus off condition
339 #ifdef CAN_WITH_STATISTICS
340                                 pchip->stat.cntBusOff++;
341 #endif /*CAN_WITH_STATISTICS */
342                                 //pchip->fifo->tx_in_progress = 0;
343                                 //reset init bit
344                                 CANMSG
345                                     ("(c%d)stat: c_can_irq_handler: Bus Off\n",
346                                      pchip->chip_idx);
347                                 /*if (pchip->stat.cntBusOff > 100)
348                                    {
349                                    CANMSG("(c%d)to much busoff warnings (>100), deactivating chip",
350                                    pchip->chip_idx);
351                                    pchip->config_irqs(pchip, 0);
352                                    pchip->enable_configuration(pchip);
353                                    pchip->clear_objects(pchip);
354                                    pchip->flags &= ~CHANNEL_CONFIGURED;
355                                    return;
356                                    }
357                                    else */
358                                 CANMSG("(c%d)try to reconnect",
359                                        pchip->chip_idx);
360                                 pchip->chipspecops->
361                                     disable_configuration(pchip);
362                         }
363
364                         if (chip_status & SR_TXOK) {
365                                 DEBUGMSG
366                                     ("(c%d)stat: Transmitted a Message successfully\n",
367                                      pchip->chip_idx);
368                                 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK,
369                                                   CCSR);
370                         }
371
372                         if (chip_status & SR_RXOK) {
373                                 DEBUGMSG
374                                     ("(c%d)stat: Received a Message successfully\n",
375                                      pchip->chip_idx);
376                                 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK,
377                                                   CCSR);
378                         }
379 #ifdef CAN_WITH_STATISTICS
380                         // Errors to statistics
381                         switch (chip_status & 0x07) {
382                         case SRLEC_NE:  // No error
383                                 break;
384                         case SRLEC_SE:  // Stuff error
385                                 pchip->stat.cntStuffErr++;
386                                 break;
387                         case SRLEC_FE:  // Form error
388                                 pchip->stat.cntFormErr++;
389                                 break;
390                         case SRLEC_AE:  // Ack error
391                                 pchip->stat.cntAckErr++;
392                                 break;
393                         case SRLEC_B1:  // Bit 1 error
394                                 pchip->stat.cntBit1Err++;
395                                 break;
396                         case SRLEC_B0:  // Bit 0 error
397                                 pchip->stat.cntBit0Err++;
398                                 break;
399                         case SRLEC_CR:  // CRC error
400                                 pchip->stat.cntCrcErr++;
401                                 break;
402                         case 7: // unused
403                                 break;
404                         }
405 #endif /*CAN_WITH_STATISTICS */
406                         //return; // continue?
407                 } else {
408                         if (irqreg >= 1 && irqreg <= 32) {
409                                 struct msgobj_t *pmsgobj;
410                                 int idxobj;
411
412                                 //get id
413                                 idxobj = irqreg - 1;
414                                 pmsgobj = pchip->msgobj[idxobj];
415
416                                 //DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",
417                                 //            (unsigned long)pchip->vbase_addr + iIRQ,
418                                 //      (unsigned long)dev_id,
419                                 //      irqreg,
420                                 //      statreg );
421                                 //
422                                 spin_lock(&c_can_if1lock);
423
424                                 //Message Lost Check
425                                 if (c_can_if1_busycheck(pchip)) ;       /*?????????? */
426                                 c_can_write_reg_w(pchip, msgLstReadMaskCM,
427                                                   CCIF1CM);
428                                 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
429
430                                 if (c_can_if1_busycheck(pchip)) ;       /*?????????? */
431                                 tempCntlReg = c_can_read_reg_w(pchip, CCIF1DMC);
432
433                                 if (tempCntlReg & IFXMC_MSGLST) {
434                                         CANMSG("(c%dm%d)Chip lost a message\n",
435                                                pchip->chip_idx,
436                                                pmsgobj->object);
437 #ifdef CAN_WITH_STATISTICS
438                                         pchip->stat.cntMsgLst++;
439 #endif /*CAN_WITH_STATISTICS */
440
441                                         //Reset Message Lost Bit
442                                         tempCntlReg =
443                                             tempCntlReg & (~IFXMC_MSGLST);
444                                         c_can_write_reg_w(pchip, tempCntlReg,
445                                                           CCIF1DMC);
446                                         c_can_write_reg_w(pchip,
447                                                           msgLstWriteMaskCM,
448                                                           CCIF1CM);
449                                         c_can_write_reg_w(pchip, idxobj + 1,
450                                                           CCIF1CR);
451                                 }
452                                 //transfer Message Object to IF1 Buffer
453                                 if (c_can_if1_busycheck(pchip)) ;
454
455                                 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
456                                 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
457
458                                 if (c_can_if1_busycheck(pchip)) ;
459                                 if (c_can_read_reg_w(pchip, CCIF1A2) &
460                                     IFXARB2_DIR) {
461                                         spin_unlock(&c_can_if1lock);
462                                         c_can_irq_write_handler(pchip, idxobj);
463
464                                         if(!pmsgobj->tx_slot){
465                                                 if(can_msgobj_test_and_clear_fl(pmsgobj, FILTCH_REQUEST)) {
466                                                         c_can_irq_update_filter(pchip, pmsgobj);
467                                                 }
468                                         }
469                                 } else {
470                                         if (can_msgobj_test_fl
471                                             (pmsgobj, RX_MODE_EXT)) {
472                                                 id0 =
473                                                     c_can_read_reg_w(pchip,
474                                                                      CCIF1A1);
475                                                 id1 =
476                                                     (c_can_read_reg_w
477                                                      (pchip,
478                                                       CCIF1A2) & 0x1FFF) << 16;
479                                                 msgid = id0 | id1;
480                                         } else {
481                                                 msgid =
482                                                     ((c_can_read_reg_w
483                                                       (pchip,
484                                                        CCIF1A2) & 0x1FFC) >> 2)
485                                                     & 0x7FF;
486                                         }
487                                         spin_unlock(&c_can_if1lock);
488
489                                         spin_lock(&hardware_p->rtr_lock);
490                                         while (rtr_search != NULL) {
491                                                 if (rtr_search->id == msgid) {
492                                                         break;
493                                                 }
494                                                 rtr_search = rtr_search->next;
495                                         }
496                                         spin_unlock(&hardware_p->rtr_lock);
497
498                                         spin_lock(&c_can_if1lock);
499
500                                         //transfer Message Object to IF1 Buffer
501                                         if (c_can_if1_busycheck(pchip)) ;
502                                         c_can_write_reg_w(pchip, readMaskCM,
503                                                           CCIF1CM);
504                                         c_can_write_reg_w(pchip, idxobj + 1,
505                                                           CCIF1CR);
506
507                                         if (c_can_if1_busycheck(pchip)) ;
508
509                                         if ((rtr_search != NULL)
510                                             && (rtr_search->id == msgid)) {
511                                                 c_can_irq_rtr_handler(pchip,
512                                                                       idxobj,
513                                                                       msgid);
514                                         } else {
515                                                 c_can_irq_read_handler(pchip,
516                                                                        idxobj,
517                                                                        msgid);
518                                         }
519                                         spin_unlock(&c_can_if1lock);
520
521                                 }
522                                 //else
523                         }
524                         //if (irqreg >= 1 && irqreg <= 32)
525                 }
526                 // Get irq status again
527                 irqreg = c_can_read_reg_w(pchip, CCINTR);
528         }
529         return CANCHIP_IRQ_HANDLED;
530 }
531
532 ///////////////////////////////////////////////////////////////////////////////
533 // c_can_irq_rtr_handler
534 //
535
536 void c_can_irq_rtr_handler(struct canchip_t *pchip, int idxobj, u32 msgid)
537 {
538         short int i = 0;
539         struct rtr_id *prtr_search = hardware_p->rtr_queue;
540         union c_can_data rtrData;
541
542         spin_lock(&hardware_p->rtr_lock);
543
544         prtr_search->rtr_message->id = msgid;
545         prtr_search->rtr_message->length =
546             (c_can_read_reg_w(pchip, CCIF1DMC) & 0x000f);
547
548         // Fetch message bytes
549         if (prtr_search->rtr_message->length > 0)
550                 rtrData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
551         if (prtr_search->rtr_message->length > 2)
552                 rtrData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
553         if (prtr_search->rtr_message->length > 4)
554                 rtrData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
555         if (prtr_search->rtr_message->length > 6)
556                 rtrData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
557
558         for (i = 0; i < prtr_search->rtr_message->length; i++) {
559                 prtr_search->rtr_message->data[i] = rtrData.bdata[i];
560         }
561
562         spin_unlock(&hardware_p->rtr_lock);
563         wake_up_interruptible(&prtr_search->rtr_wq);
564         return;
565 }