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"
19 unsigned short wdata[4];
20 unsigned char bdata[8];
26 inline void c_can_irq_read_handler( struct canchip_t *pchip, int idxobj, u32 msgid );
28 inline void c_can_irq_write_handler( struct canchip_t *pchip, int idxobj);
30 void c_can_irq_rtr_handler( struct canchip_t *pchip, int idxobj, u32 msgid );
32 u16 readMaskCM = IFXCM_ARB | IFXCM_CNTRL | IFXCM_CLRINTPND
33 | IFXCM_TRND | IFXCM_DA | IFXCM_DB;
35 u16 msgLstReadMaskCM = IFXCM_CNTRL;
36 u16 msgLstWriteMaskCM = IFXCM_CNTRL | IFXCM_WRRD;
38 ///////////////////////////////////////////////////////////////////////////////
39 // c_can_irq_write_handler
41 // Send a message from the output fifo ( if any ).
44 inline void c_can_irq_write_handler( struct canchip_t *pchip, int idxobj)
47 struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
49 DEBUGMSG("(c%dm%d)calling c_can_irq_write_handler(...)\n",
50 pchip->chip_idx, pmsgobj->object);
53 /* Do local transmitted message distribution if enabled */
55 /* fill CAN message timestamp */
56 can_filltimestamp(&pmsgobj->tx_slot->msg.timestamp);
58 pmsgobj->tx_slot->msg.flags |= MSG_LOCAL;
59 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->tx_slot->msg);
61 /* Free transmitted slot */
62 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge, pmsgobj->tx_slot);
63 pmsgobj->tx_slot=NULL;
66 // Get ready to send next message
67 spin_lock( &c_can_spwlock );
69 cmd=canque_test_outslot(pmsgobj->qends, &pmsgobj->tx_qedge, &pmsgobj->tx_slot);
71 DEBUGMSG("(c%dm%d)Nothin to write\n",
72 pchip->chip_idx, pmsgobj->object);
73 spin_unlock( &c_can_spwlock );
78 if ( pchip->chipspecops->send_msg( pchip, pmsgobj,&pmsgobj->tx_slot->msg) ) {
80 canque_notify_inends(pmsgobj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
81 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge, pmsgobj->tx_slot);
82 pmsgobj->tx_slot=NULL;
83 spin_unlock( &c_can_spwlock );
84 DEBUGMSG("(c%dm%d)c_can_irq_handler: Unable to send message\n",
85 pchip->chip_idx, pmsgobj->object );
88 // Another message sent
89 #ifdef CAN_WITH_STATISTICS
90 pchip->stat.cntTxPkt++;
91 pchip->stat.cntTxData += pmsgobj->tx_slot->length;
92 #endif /*CAN_WITH_STATISTICS*/
94 spin_unlock( &c_can_spwlock );
96 // Wake up any waiting writer
100 ///////////////////////////////////////////////////////////////////////////////
101 // c_can_irq_read_handler
103 // Message received form the line. Write it in the input fifo->
106 inline void c_can_irq_read_handler( struct canchip_t *pchip,
107 int idxobj, u32 msgid )
112 union c_can_data readData;
113 struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
115 DEBUGMSG("(c%dm%d)calling c_can_irq_read_handler(...)\n",
116 pchip->chip_idx, pmsgobj->object);
118 while ( bDataAvail ) {
120 #ifdef CAN_WITH_STATISTICS
121 pchip->stat.cntRxFifoOvr++;
122 #endif /*CAN_WITH_STATISTICS*/
124 msgCntlReg = c_can_read_reg_w( pchip, CCIF1DMC );
126 pmsgobj->rx_msg.length = msgCntlReg & 0x000F;
129 pmsgobj->rx_msg.id = (u32)msgid;
131 // Fetch message bytes
132 if (pmsgobj->rx_msg.length > 0)
133 readData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
134 if (pmsgobj->rx_msg.length > 2)
135 readData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
136 if (pmsgobj->rx_msg.length > 4)
137 readData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
138 if (pmsgobj->rx_msg.length > 6)
139 readData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
141 for ( i=0; i < pmsgobj->rx_msg.length; i++ ) {
142 pmsgobj->rx_msg.data[ i ] = readData.bdata[i];
144 DEBUGMSG("(c%dm%d)Received Message:\n",
145 pchip->chip_idx, pmsgobj->object);
146 DEBUGMSG(" id = %ld\n",
148 DEBUGMSG(" length = %d\n",
149 pmsgobj->rx_msg.length);
150 for ( i=0; i < pmsgobj->rx_msg.length; i++ )
151 DEBUGMSG(" data[%d] = 0x%.2x\n", i, pmsgobj->rx_msg.data[i]);
153 /* fill CAN message timestamp */
154 can_filltimestamp(&pmsgobj->rx_msg.timestamp);
156 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->rx_msg);
158 #ifdef CAN_WITH_STATISTICS
159 // Another received packet
160 pchip->stat.cntRxPkt++;
162 // Add databytes read to statistics block
163 pchip->stat.cntRxData += pmsgobj->rx_msg.length;
164 #endif /*CAN_WITH_STATISTICS*/
166 // Check if new data arrived
167 if (c_can_if1_busycheck(pchip)) ;
168 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
169 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
170 if (c_can_if1_busycheck(pchip)) ;
171 if ( !( ( bDataAvail = c_can_read_reg_w( pchip, CCIF1DMC ) ) &
176 if ( bDataAvail & IFXMC_MSGLST ) {
177 CANMSG("(c%dm%d)c-can fifo full: Message lost!\n",
178 pchip->chip_idx, pmsgobj->object);
185 void c_can_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
187 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
189 /*if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
190 if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
191 i82527_irq_write_handler(chip, obj);
195 if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
196 i82527_irq_update_filter(chip, obj);
199 /* FIXME: these functionality has to be implemented to start TX */
201 can_msgobj_clear_fl(obj,TX_LOCK);
202 if(can_msgobj_test_fl(obj,TX_REQUEST))
204 if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot)
211 ///////////////////////////////////////////////////////////////////////////////
215 int c_can_irq_handler(int irq, struct canchip_t *pchip)
217 struct rtr_id *rtr_search = hardware_p->rtr_queue;
226 irqreg = c_can_read_reg_w( pchip, CCINTR );
229 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx spurious interrupt\n",
231 (long)( pchip->/*v*/chip_base_addr/* + CCSR*/));
232 return CANCHIP_IRQ_NONE;
235 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x\n",
237 (long)( pchip->/*v*/chip_base_addr/* + CCSR*/),
243 c_can_registerdump(pchip);
247 // Handle change in status register
249 if ( irqreg == INT_STAT ) {
250 chip_status = c_can_read_reg_w( pchip, CCSR );
251 DEBUGMSG( "(c%d)Status register: 0x%x\n",
252 pchip->chip_idx, chip_status );
254 if ( chip_status & SR_EWARN ) {
255 // There is an abnormal # of errors
256 #ifdef CAN_WITH_STATISTICS
257 pchip->stat.cntWarnings++;
258 #endif /*CAN_WITH_STATISTICS*/
259 errcount = c_can_read_reg_w( pchip, CCEC);
260 DEBUGMSG("(c%d)stat: c_can_irq_handler: Abnormal number of Errors Warning\n"
261 " txErr=%d, rxErr=%d\n",
262 pchip->chip_idx, (errcount&0x00ff), ((errcount&0x7f00)>>8));
265 // this code deactivates the chip if the transmiterrorcounter grew above 127
266 if ((pchip->stat.cntWarnings > 100) && ((errcount&0x00ff) > 127))
268 CANMSG("(c%d)to much Errornumber warnings (>100), deactivating chip",
270 pchip->config_irqs(pchip, 0);
271 pchip->enable_configuration(pchip);
272 pchip->clear_objects(pchip);
273 pchip->flags &= ~CHANNEL_CONFIGURED;
278 if ( chip_status & SR_EPASS ) {
279 // There is an abnormal # of errors
280 #ifdef CAN_WITH_STATISTICS
281 pchip->stat.cntErrPassive++;
282 #endif /*CAN_WITH_STATISTICS*/
283 DEBUGMSG("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
287 if ( chip_status & SR_BOFF ) {
288 // We have a bus off condition
289 #ifdef CAN_WITH_STATISTICS
290 pchip->stat.cntBusOff++;
291 #endif /*CAN_WITH_STATISTICS*/
292 //pchip->fifo->tx_in_progress = 0;
294 CANMSG("(c%d)stat: c_can_irq_handler: Bus Off\n",
296 /*if (pchip->stat.cntBusOff > 100)
298 CANMSG("(c%d)to much busoff warnings (>100), deactivating chip",
300 pchip->config_irqs(pchip, 0);
301 pchip->enable_configuration(pchip);
302 pchip->clear_objects(pchip);
303 pchip->flags &= ~CHANNEL_CONFIGURED;
307 CANMSG("(c%d)try to reconnect",
309 pchip->chipspecops->disable_configuration(pchip);
312 if (chip_status & SR_TXOK) {
313 DEBUGMSG("(c%d)stat: Transmitted a Message successfully\n",
315 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK, CCSR);
318 if (chip_status & SR_RXOK) {
319 DEBUGMSG("(c%d)stat: Received a Message successfully\n",
321 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK, CCSR);
324 #ifdef CAN_WITH_STATISTICS
325 // Errors to statistics
326 switch( chip_status & 0x07 )
328 case SRLEC_NE: // No error
330 case SRLEC_SE: // Stuff error
331 pchip->stat.cntStuffErr++;
333 case SRLEC_FE: // Form error
334 pchip->stat.cntFormErr++;
336 case SRLEC_AE: // Ack error
337 pchip->stat.cntAckErr++;
339 case SRLEC_B1: // Bit 1 error
340 pchip->stat.cntBit1Err++;
342 case SRLEC_B0: // Bit 0 error
343 pchip->stat.cntBit0Err++;
345 case SRLEC_CR: // CRC error
346 pchip->stat.cntCrcErr++;
351 #endif /*CAN_WITH_STATISTICS*/
352 //return; // continue?
354 if (irqreg >0 && irqreg <33) {
355 struct msgobj_t *pmsgobj;
360 pmsgobj=pchip->msgobj[idxobj];
362 //DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",
363 // (unsigned long)pchip->vbase_addr + iIRQ,
364 // (unsigned long)dev_id,
368 spin_lock( &c_can_if1lock );
371 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
372 c_can_write_reg_w(pchip, msgLstReadMaskCM, CCIF1CM);
373 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
375 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
376 tempCntlReg = c_can_read_reg_w( pchip, CCIF1DMC );
378 if (tempCntlReg & IFXMC_MSGLST) {
379 CANMSG("(c%dm%d)Chip lost a message\n",
380 pchip->chip_idx, pmsgobj->object);
381 #ifdef CAN_WITH_STATISTICS
382 pchip->stat.cntMsgLst++;
383 #endif /*CAN_WITH_STATISTICS*/
385 //Reset Message Lost Bit
386 tempCntlReg = tempCntlReg & (~IFXMC_MSGLST);
387 c_can_write_reg_w(pchip, tempCntlReg, CCIF1DMC);
388 c_can_write_reg_w(pchip, msgLstWriteMaskCM, CCIF1CM);
389 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
392 //transfer Message Object to IF1 Buffer
393 if (c_can_if1_busycheck(pchip)) ;
394 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
395 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
397 if (c_can_if1_busycheck(pchip)) ;
398 if (c_can_read_reg_w(pchip, CCIF1A2) & IFXARB2_DIR) {
399 spin_unlock( &c_can_if1lock );
400 c_can_irq_write_handler(pchip,idxobj);
402 if (can_msgobj_test_fl(pmsgobj,RX_MODE_EXT)) {
403 id0=c_can_read_reg_w(pchip, CCIF1A1);
404 id1=(c_can_read_reg_w(pchip, CCIF1A2)&0x1FFF)<<16;
407 msgid=((c_can_read_reg_w(pchip, CCIF1A2)&0x1FFC)>>2)&0x7FF;
409 spin_unlock( &c_can_if1lock );
411 spin_lock(&hardware_p->rtr_lock);
412 while ( rtr_search != NULL )
414 if ( rtr_search->id == msgid ) {
417 rtr_search = rtr_search->next;
419 spin_unlock(&hardware_p->rtr_lock);
421 spin_lock( &c_can_if1lock );
423 //transfer Message Object to IF1 Buffer
424 if (c_can_if1_busycheck(pchip)) ;
425 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
426 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
428 if (c_can_if1_busycheck(pchip)) ;
430 if ( ( rtr_search != NULL ) && (rtr_search->id == msgid ) ) {
431 c_can_irq_rtr_handler( pchip, idxobj, msgid );
433 c_can_irq_read_handler( pchip, idxobj, msgid );
435 spin_unlock( &c_can_if1lock );
443 // Get irq status again
444 irqreg = c_can_read_reg_w( pchip, CCINTR );
446 return CANCHIP_IRQ_HANDLED;
449 ///////////////////////////////////////////////////////////////////////////////
450 // c_can_irq_rtr_handler
453 void c_can_irq_rtr_handler( struct canchip_t *pchip, int idxobj, u32 msgid )
456 struct rtr_id *prtr_search = hardware_p->rtr_queue;
457 union c_can_data rtrData;
459 spin_lock( &hardware_p->rtr_lock );
461 prtr_search->rtr_message->id = msgid;
462 prtr_search->rtr_message->length =
463 ( c_can_read_reg_w( pchip, CCIF1DMC ) & 0x000f);
465 // Fetch message bytes
466 if (prtr_search->rtr_message->length > 0)
467 rtrData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
468 if (prtr_search->rtr_message->length > 2)
469 rtrData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
470 if (prtr_search->rtr_message->length > 4)
471 rtrData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
472 if (prtr_search->rtr_message->length > 6)
473 rtrData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
475 for ( i=0; i<prtr_search->rtr_message->length; i++ ) {
476 prtr_search->rtr_message->data[ i ] = rtrData.bdata[i];
479 spin_unlock( &hardware_p->rtr_lock );
480 wake_up_interruptible( &prtr_search->rtr_wq );