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 spin_unlock( &c_can_sprlock );
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 void c_can_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
189 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
191 /*if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
192 if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
193 i82527_irq_write_handler(chip, obj);
197 if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
198 i82527_irq_update_filter(chip, obj);
201 /* FIXME: these functionality has to be implemented to start TX */
203 can_msgobj_clear_fl(obj,TX_LOCK);
204 if(can_msgobj_test_fl(obj,TX_REQUEST))
206 if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot)
213 ///////////////////////////////////////////////////////////////////////////////
217 int c_can_irq_handler(int irq, struct canchip_t *chip)
219 struct rtr_id *rtr_search = hardware_p->rtr_queue;
227 // u32 intCntrVAddr = 0;
229 //unsigned short flags = 0;
231 //if (pchip->ntype != CAN_CHIPTYPE_C_CAN) {
232 // DEBUGMSG("\n(c%d)IRQ not for c_can_irq_handler(...)\n", pchip->chip_idx);
236 irqreg = c_can_read_reg_w( pchip, CCINTR );
239 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx spurious interrupt\n",
241 (long)( pchip->/*v*/chip_base_addr/* + CCSR*/));
242 return CANCHIP_IRQ_NONE;
245 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x\n",
247 (long)( pchip->/*v*/chip_base_addr/* + CCSR*/),
253 c_can_registerdump(pchip);
258 if ( (!( intCntrVAddr = (u32)ioremap( 0x80024000, 0xCD ) ))) {
259 DEBUGMSG("Failed to map Interrupt Controller IO-memory\n");
263 DEBUGMSG( "Mapped Interrupt Controller IO-memory: 0x%lx - 0x%lx to 0x%lx\n",
264 (unsigned long)0X80024000,
265 (unsigned long)0X800240CC,
266 (unsigned long)intCntrVAddr);
269 DEBUGMSG("Current Interrupt Status Register (ISR): 0x%4.4lx\n",
270 (long)readl(intCntrVAddr + 4));
271 DEBUGMSG("Current Interrupt ID: %d\n",
272 (int)(readl(intCntrVAddr + 0x90) & 0xF));
273 iounmap( (void*)intCntrVAddr);
274 DEBUGMSG( "Unmapped Interrupt Controller IO-memory: 0x%lx\n",
275 (unsigned long)intCntrVAddr);
279 // Handle change in status register
281 if ( irqreg == INT_STAT ) {
282 chip_status = c_can_read_reg_w( pchip, CCSR );
283 DEBUGMSG( "(c%d)Status register: 0x%x\n",
284 pchip->chip_idx, chip_status );
286 if ( chip_status & SR_EWARN ) {
287 // There is an abnormal # of errors
288 #ifdef CAN_WITH_STATISTICS
289 pchip->stat.cntWarnings++;
290 #endif /*CAN_WITH_STATISTICS*/
291 errcount = c_can_read_reg_w( pchip, CCEC);
292 DEBUGMSG("(c%d)stat: c_can_irq_handler: Abnormal number of Errors Warning\n"
293 " txErr=%d, rxErr=%d\n",
294 pchip->chip_idx, (errcount&0x00ff), ((errcount&0x7f00)>>8));
297 // this code deactivates the chip if the transmiterrorcounter grew above 127
298 if ((pchip->stat.cntWarnings > 100) && ((errcount&0x00ff) > 127))
300 CANMSG("(c%d)to much Errornumber warnings (>100), deactivating chip",
302 pchip->config_irqs(pchip, 0);
303 pchip->enable_configuration(pchip);
304 pchip->clear_objects(pchip);
305 pchip->flags &= ~CHANNEL_CONFIGURED;
310 if ( chip_status & SR_EPASS ) {
311 // There is an abnormal # of errors
312 #ifdef CAN_WITH_STATISTICS
313 pchip->stat.cntErrPassive++;
314 #endif /*CAN_WITH_STATISTICS*/
315 DEBUGMSG("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
319 if ( chip_status & SR_BOFF ) {
320 // We have a bus off condition
321 #ifdef CAN_WITH_STATISTICS
322 pchip->stat.cntBusOff++;
323 #endif /*CAN_WITH_STATISTICS*/
324 //pchip->fifo->tx_in_progress = 0;
326 CANMSG("(c%d)stat: c_can_irq_handler: Bus Off\n",
328 /*if (pchip->stat.cntBusOff > 100)
330 CANMSG("(c%d)to much busoff warnings (>100), deactivating chip",
332 pchip->config_irqs(pchip, 0);
333 pchip->enable_configuration(pchip);
334 pchip->clear_objects(pchip);
335 pchip->flags &= ~CHANNEL_CONFIGURED;
339 CANMSG("(c%d)try to reconnect",
341 pchip->chipspecops->disable_configuration(pchip);
344 if (chip_status & SR_TXOK) {
345 DEBUGMSG("(c%d)stat: Transmitted a Message successfully\n",
347 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK, CCSR);
350 if (chip_status & SR_RXOK) {
351 DEBUGMSG("(c%d)stat: Received a Message successfully\n",
353 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK, CCSR);
356 #ifdef CAN_WITH_STATISTICS
357 // Errors to statistics
358 switch( chip_status & 0x07 )
360 case SRLEC_NE: // No error
362 case SRLEC_SE: // Stuff error
363 pchip->stat.cntStuffErr++;
365 case SRLEC_FE: // Form error
366 pchip->stat.cntFormErr++;
368 case SRLEC_AE: // Ack error
369 pchip->stat.cntAckErr++;
371 case SRLEC_B1: // Bit 1 error
372 pchip->stat.cntBit1Err++;
374 case SRLEC_B0: // Bit 0 error
375 pchip->stat.cntBit0Err++;
377 case SRLEC_CR: // CRC error
378 pchip->stat.cntCrcErr++;
383 #endif /*CAN_WITH_STATISTICS*/
384 //return; // continue?
386 if (irqreg >0 && irqreg <33) {
387 struct msgobj_t *pmsgobj;
392 pmsgobj=pchip->msgobj[idxobj];
394 //DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",
395 // (unsigned long)pchip->vbase_addr + iIRQ,
396 // (unsigned long)dev_id,
400 spin_lock( &c_can_if1lock );
403 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
404 c_can_write_reg_w(pchip, msgLstReadMaskCM, CCIF1CM);
405 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
407 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
408 tempCntlReg = c_can_read_reg_w( pchip, CCIF1DMC );
410 if (tempCntlReg & IFXMC_MSGLST) {
411 CANMSG("(c%dm%d)Chip lost a message\n",
412 pchip->chip_idx, pmsgobj->object);
413 #ifdef CAN_WITH_STATISTICS
414 pchip->stat.cntMsgLst++;
415 #endif /*CAN_WITH_STATISTICS*/
417 //Reset Message Lost Bit
418 tempCntlReg = tempCntlReg & (~IFXMC_MSGLST);
419 c_can_write_reg_w(pchip, tempCntlReg, CCIF1DMC);
420 c_can_write_reg_w(pchip, msgLstWriteMaskCM, CCIF1CM);
421 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
424 //transfer Message Object to IF1 Buffer
425 if (c_can_if1_busycheck(pchip)) ;
426 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
427 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
429 if (c_can_if1_busycheck(pchip)) ;
430 if (c_can_read_reg_w(pchip, CCIF1A2) & IFXARB2_DIR) {
431 spin_unlock( &c_can_if1lock );
432 c_can_irq_write_handler(pchip,idxobj);
434 if (can_msgobj_test_fl(pmsgobj,RX_MODE_EXT)) {
435 id0=c_can_read_reg_w(pchip, CCIF1A1);
436 id1=(c_can_read_reg_w(pchip, CCIF1A2)&0x1FFF)<<16;
439 msgid=((c_can_read_reg_w(pchip, CCIF1A2)&0x1FFC)>>2)&0x7FF;
441 spin_unlock( &c_can_if1lock );
443 spin_lock(&hardware_p->rtr_lock);
444 while ( rtr_search != NULL )
446 if ( rtr_search->id == msgid ) {
449 rtr_search = rtr_search->next;
451 spin_unlock(&hardware_p->rtr_lock);
453 spin_lock( &c_can_if1lock );
455 //transfer Message Object to IF1 Buffer
456 if (c_can_if1_busycheck(pchip)) ;
457 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
458 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
460 if (c_can_if1_busycheck(pchip)) ;
462 if ( ( rtr_search != NULL ) && (rtr_search->id == msgid ) ) {
463 c_can_irq_rtr_handler( pchip, idxobj, msgid );
465 c_can_irq_read_handler( pchip, idxobj, msgid );
467 spin_unlock( &c_can_if1lock );
475 // Get irq status again
476 irqreg = c_can_read_reg_w( pchip, CCINTR );
478 return CANCHIP_IRQ_HANDLED;
481 ///////////////////////////////////////////////////////////////////////////////
482 // c_can_irq_rtr_handler
485 void c_can_irq_rtr_handler( struct canchip_t *pchip, int idxobj, u32 msgid )
488 struct rtr_id *prtr_search = hardware_p->rtr_queue;
489 union c_can_data rtrData;
491 spin_lock( &hardware_p->rtr_lock );
493 prtr_search->rtr_message->id = msgid;
494 prtr_search->rtr_message->length =
495 ( c_can_read_reg_w( pchip, CCIF1DMC ) & 0x000f);
497 // Fetch message bytes
498 if (prtr_search->rtr_message->length > 0)
499 rtrData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
500 if (prtr_search->rtr_message->length > 2)
501 rtrData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
502 if (prtr_search->rtr_message->length > 4)
503 rtrData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
504 if (prtr_search->rtr_message->length > 6)
505 rtrData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
507 for ( i=0; i<prtr_search->rtr_message->length; i++ ) {
508 prtr_search->rtr_message->data[ i ] = rtrData.bdata[i];
511 spin_unlock( &hardware_p->rtr_lock );
512 wake_up_interruptible( &prtr_search->rtr_wq );