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
12 #include "../include/can.h"
13 #include "../include/can_sysdep.h"
14 #include "../include/main.h"
15 #include "../include/c_can.h"
18 unsigned short wdata[4];
19 unsigned char bdata[8];
23 inline void c_can_irq_read_handler(struct canchip_t *pchip, int idxobj,
26 inline void c_can_irq_write_handler(struct canchip_t *pchip, int idxobj);
28 void c_can_irq_rtr_handler(struct canchip_t *pchip, int idxobj, u32 msgid);
30 u16 readMaskCM = IFXCM_ARB | IFXCM_CNTRL | IFXCM_CLRINTPND
31 | IFXCM_TRND | IFXCM_DA | IFXCM_DB;
33 u16 msgLstReadMaskCM = IFXCM_CNTRL;
34 u16 msgLstWriteMaskCM = IFXCM_CNTRL | IFXCM_WRRD;
36 ///////////////////////////////////////////////////////////////////////////////
37 // c_can_irq_write_handler
39 // Send a message from the output fifo ( if any ).
42 inline void c_can_irq_write_handler(struct canchip_t *pchip, int idxobj)
45 struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
47 DEBUGMSG("(c%dm%d)calling c_can_irq_write_handler(...)\n",
48 pchip->chip_idx, pmsgobj->object);
50 if (pmsgobj->tx_slot) {
51 /* Do local transmitted message distribution if enabled */
53 /* fill CAN message timestamp */
54 can_filltimestamp(&pmsgobj->tx_slot->msg.timestamp);
56 pmsgobj->tx_slot->msg.flags |= MSG_LOCAL;
57 canque_filter_msg2edges(pmsgobj->qends,
58 &pmsgobj->tx_slot->msg);
60 /* Free transmitted slot */
61 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge,
63 pmsgobj->tx_slot = NULL;
65 // Get ready to send next message
66 spin_lock(&c_can_spwlock);
69 canque_test_outslot(pmsgobj->qends, &pmsgobj->tx_qedge,
72 DEBUGMSG("(c%dm%d)Nothin to write\n",
73 pchip->chip_idx, pmsgobj->object);
74 spin_unlock(&c_can_spwlock);
78 if (pchip->chipspecops->
79 send_msg(pchip, pmsgobj, &pmsgobj->tx_slot->msg)) {
81 canque_notify_inends(pmsgobj->tx_qedge,
82 CANQUEUE_NOTIFY_ERRTX_SEND);
83 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge,
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);
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 */
97 spin_unlock(&c_can_spwlock);
99 // Wake up any waiting writer
103 ///////////////////////////////////////////////////////////////////////////////
104 // c_can_irq_read_handler
106 // Message received form the line. Write it in the input fifo->
109 inline void c_can_irq_read_handler(struct canchip_t *pchip,
110 int idxobj, u32 msgid)
115 union c_can_data readData;
116 struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
118 DEBUGMSG("(c%dm%d)calling c_can_irq_read_handler(...)\n",
119 pchip->chip_idx, pmsgobj->object);
123 #ifdef CAN_WITH_STATISTICS
124 pchip->stat.cntRxFifoOvr++;
125 #endif /*CAN_WITH_STATISTICS */
127 msgCntlReg = c_can_read_reg_w(pchip, CCIF1DMC);
129 pmsgobj->rx_msg.length = msgCntlReg & 0x000F;
132 pmsgobj->rx_msg.id = (u32) msgid;
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);
144 for (i = 0; i < pmsgobj->rx_msg.length; i++) {
145 pmsgobj->rx_msg.data[i] = readData.bdata[i];
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]);
155 /* fill CAN message timestamp */
156 can_filltimestamp(&pmsgobj->rx_msg.timestamp);
158 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->rx_msg);
160 #ifdef CAN_WITH_STATISTICS
161 // Another received packet
162 pchip->stat.cntRxPkt++;
164 // Add databytes read to statistics block
165 pchip->stat.cntRxData += pmsgobj->rx_msg.length;
166 #endif /*CAN_WITH_STATISTICS */
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)) &
178 if (bDataAvail & IFXMC_MSGLST) {
179 CANMSG("(c%dm%d)c-can fifo full: Message lost!\n",
180 pchip->chip_idx, pmsgobj->object);
187 ///////////////////////////////////////////////////////////////////////////////
188 // c_can_irq_update_filter
190 // update acceptance filter for given object.
193 void c_can_irq_update_filter(struct canchip_t *pchip, struct msgobj_t *obj)
195 struct canfilt_t filt;
197 if(canqueue_ends_filt_conjuction(obj->qends, &filt)) {
198 obj->rx_preconfig_id=filt.id;
200 if (filt.flags&MSG_EXT)
201 can_msgobj_set_fl(obj,RX_MODE_EXT);
203 can_msgobj_clear_fl(obj,RX_MODE_EXT);
205 c_can_mask(obj, filt.mask, 0);
207 c_can_pre_read_config(pchip, obj);
209 CANMSG("c_can_irq_update_filter: obj #%d\n",obj->object);
213 ///////////////////////////////////////////////////////////////////////////////
214 // c_can_irq_sync_activities
216 // ensure, that not requests for object activities are serialized.
219 void c_can_irq_sync_activities(struct canchip_t *pchip, struct msgobj_t *obj)
221 while (!can_msgobj_test_and_set_fl(obj, TX_LOCK)) {
223 if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
225 int idxobj = obj->object-1;
228 DEBUGMSG("c_can_irq_sync_activities wrong idxobj\n");
233 cctreqx = c_can_read_reg_w(pchip, CCTREQ1);
235 cctreqx = c_can_read_reg_w(pchip, CCTREQ2);
237 if (!(cctreqx & (1 << (idxobj & 0xf)))) {
238 can_msgobj_clear_fl(obj, TX_REQUEST);
239 c_can_irq_write_handler(pchip, idxobj);
244 if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
245 c_can_irq_update_filter(pchip, obj);
249 can_msgobj_clear_fl(obj, TX_LOCK);
253 if (can_msgobj_test_fl(obj, TX_REQUEST))
255 if (can_msgobj_test_fl(obj, FILTCH_REQUEST) && !obj->tx_slot)
261 ///////////////////////////////////////////////////////////////////////////////
265 int c_can_irq_handler(int irq, struct canchip_t *pchip)
267 struct rtr_id *rtr_search = hardware_p->rtr_queue;
269 int id0 = 0, id1 = 0;
275 irqreg = c_can_read_reg_w(pchip, CCINTR);
278 DEBUGMSG("\n(c%d)IRQ handler: addr=%.8lx spurious interrupt\n",
280 (long)(pchip-> /*v */ chip_base_addr /* + CCSR */ ));
281 return CANCHIP_IRQ_NONE;
284 DEBUGMSG("\n(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x\n",
286 (long)(pchip-> /*v */ chip_base_addr /* + CCSR */ ),
290 c_can_registerdump(pchip);
294 // Handle change in status register
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);
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);
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));
314 // this code deactivates the chip if the transmiterrorcounter grew above 127
315 if ((pchip->stat.cntWarnings > 100) && ((errcount&0x00ff) > 127))
317 CANMSG("(c%d)to much Errornumber warnings (>100), deactivating chip",
319 pchip->config_irqs(pchip, 0);
320 pchip->enable_configuration(pchip);
321 pchip->clear_objects(pchip);
322 pchip->flags &= ~CHANNEL_CONFIGURED;
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 */
333 ("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
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;
345 ("(c%d)stat: c_can_irq_handler: Bus Off\n",
347 /*if (pchip->stat.cntBusOff > 100)
349 CANMSG("(c%d)to much busoff warnings (>100), deactivating chip",
351 pchip->config_irqs(pchip, 0);
352 pchip->enable_configuration(pchip);
353 pchip->clear_objects(pchip);
354 pchip->flags &= ~CHANNEL_CONFIGURED;
358 CANMSG("(c%d)try to reconnect",
361 disable_configuration(pchip);
364 if (chip_status & SR_TXOK) {
366 ("(c%d)stat: Transmitted a Message successfully\n",
368 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK,
372 if (chip_status & SR_RXOK) {
374 ("(c%d)stat: Received a Message successfully\n",
376 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK,
379 #ifdef CAN_WITH_STATISTICS
380 // Errors to statistics
381 switch (chip_status & 0x07) {
382 case SRLEC_NE: // No error
384 case SRLEC_SE: // Stuff error
385 pchip->stat.cntStuffErr++;
387 case SRLEC_FE: // Form error
388 pchip->stat.cntFormErr++;
390 case SRLEC_AE: // Ack error
391 pchip->stat.cntAckErr++;
393 case SRLEC_B1: // Bit 1 error
394 pchip->stat.cntBit1Err++;
396 case SRLEC_B0: // Bit 0 error
397 pchip->stat.cntBit0Err++;
399 case SRLEC_CR: // CRC error
400 pchip->stat.cntCrcErr++;
405 #endif /*CAN_WITH_STATISTICS */
406 //return; // continue?
408 if (irqreg >= 1 && irqreg <= 32) {
409 struct msgobj_t *pmsgobj;
414 pmsgobj = pchip->msgobj[idxobj];
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,
422 spin_lock(&c_can_if1lock);
425 if (c_can_if1_busycheck(pchip)) ; /*?????????? */
426 c_can_write_reg_w(pchip, msgLstReadMaskCM,
428 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
430 if (c_can_if1_busycheck(pchip)) ; /*?????????? */
431 tempCntlReg = c_can_read_reg_w(pchip, CCIF1DMC);
433 if (tempCntlReg & IFXMC_MSGLST) {
434 CANMSG("(c%dm%d)Chip lost a message\n",
437 #ifdef CAN_WITH_STATISTICS
438 pchip->stat.cntMsgLst++;
439 #endif /*CAN_WITH_STATISTICS */
441 //Reset Message Lost Bit
443 tempCntlReg & (~IFXMC_MSGLST);
444 c_can_write_reg_w(pchip, tempCntlReg,
446 c_can_write_reg_w(pchip,
449 c_can_write_reg_w(pchip, idxobj + 1,
452 //transfer Message Object to IF1 Buffer
453 if (c_can_if1_busycheck(pchip)) ;
455 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
456 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
458 if (c_can_if1_busycheck(pchip)) ;
459 if (c_can_read_reg_w(pchip, CCIF1A2) &
461 spin_unlock(&c_can_if1lock);
462 c_can_irq_write_handler(pchip, idxobj);
464 if(!pmsgobj->tx_slot){
465 if(can_msgobj_test_and_clear_fl(pmsgobj, FILTCH_REQUEST)) {
466 c_can_irq_update_filter(pchip, pmsgobj);
470 if (can_msgobj_test_fl
471 (pmsgobj, RX_MODE_EXT)) {
473 c_can_read_reg_w(pchip,
478 CCIF1A2) & 0x1FFF) << 16;
484 CCIF1A2) & 0x1FFC) >> 2)
487 spin_unlock(&c_can_if1lock);
489 spin_lock(&hardware_p->rtr_lock);
490 while (rtr_search != NULL) {
491 if (rtr_search->id == msgid) {
494 rtr_search = rtr_search->next;
496 spin_unlock(&hardware_p->rtr_lock);
498 spin_lock(&c_can_if1lock);
500 //transfer Message Object to IF1 Buffer
501 if (c_can_if1_busycheck(pchip)) ;
502 c_can_write_reg_w(pchip, readMaskCM,
504 c_can_write_reg_w(pchip, idxobj + 1,
507 if (c_can_if1_busycheck(pchip)) ;
509 if ((rtr_search != NULL)
510 && (rtr_search->id == msgid)) {
511 c_can_irq_rtr_handler(pchip,
515 c_can_irq_read_handler(pchip,
519 spin_unlock(&c_can_if1lock);
524 //if (irqreg >= 1 && irqreg <= 32)
526 // Get irq status again
527 irqreg = c_can_read_reg_w(pchip, CCINTR);
529 return CANCHIP_IRQ_HANDLED;
532 ///////////////////////////////////////////////////////////////////////////////
533 // c_can_irq_rtr_handler
536 void c_can_irq_rtr_handler(struct canchip_t *pchip, int idxobj, u32 msgid)
539 struct rtr_id *prtr_search = hardware_p->rtr_queue;
540 union c_can_data rtrData;
542 spin_lock(&hardware_p->rtr_lock);
544 prtr_search->rtr_message->id = msgid;
545 prtr_search->rtr_message->length =
546 (c_can_read_reg_w(pchip, CCIF1DMC) & 0x000f);
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);
558 for (i = 0; i < prtr_search->rtr_message->length; i++) {
559 prtr_search->rtr_message->data[i] = rtrData.bdata[i];
562 spin_unlock(&hardware_p->rtr_lock);
563 wake_up_interruptible(&prtr_search->rtr_wq);