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.2 9 Jul 2003
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 chip_t *pchip, int idxobj, u32 msgid );
28 inline void c_can_irq_write_handler( struct chip_t *pchip, int idxobj);
30 void c_can_irq_rtr_handler( struct chip_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 chip_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 pmsgobj->tx_slot->msg.flags |= MSG_LOCAL;
56 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->tx_slot->msg);
58 /* Free transmitted slot */
59 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge, pmsgobj->tx_slot);
60 pmsgobj->tx_slot=NULL;
63 // Get ready to send next message
64 spin_lock( &c_can_spwlock );
66 cmd=canque_test_outslot(pmsgobj->qends, &pmsgobj->tx_qedge, &pmsgobj->tx_slot);
68 DEBUGMSG("(c%dm%d)Nothin to write\n",
69 pchip->chip_idx, pmsgobj->object);
70 spin_unlock( &c_can_spwlock );
75 if ( pchip->chipspecops->send_msg( pchip, pmsgobj,&pmsgobj->tx_slot->msg) ) {
77 canque_notify_inends(pmsgobj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
78 canque_free_outslot(pmsgobj->qends, pmsgobj->tx_qedge, pmsgobj->tx_slot);
79 pmsgobj->tx_slot=NULL;
80 spin_unlock( &c_can_spwlock );
81 DEBUGMSG("(c%dm%d)c_can_irq_handler: Unable to send message\n",
82 pchip->chip_idx, pmsgobj->object );
85 // Another message sent
86 #ifdef CAN_WITH_STATISTICS
87 pchip->stat.cntTxPkt++;
88 pchip->stat.cntTxData += pmsgobj->tx_slot->length;
89 #endif /*CAN_WITH_STATISTICS*/
91 spin_unlock( &c_can_spwlock );
93 // Wake up any waiting writer
97 ///////////////////////////////////////////////////////////////////////////////
98 // c_can_irq_read_handler
100 // Message received form the line. Write it in the input fifo->
103 inline void c_can_irq_read_handler( struct chip_t *pchip,
104 int idxobj, u32 msgid )
109 union c_can_data readData;
110 struct msgobj_t *pmsgobj = pchip->msgobj[idxobj];
112 DEBUGMSG("(c%dm%d)calling c_can_irq_read_handler(...)\n",
113 pchip->chip_idx, pmsgobj->object);
115 while ( bDataAvail ) {
117 #ifdef CAN_WITH_STATISTICS
118 pchip->stat.cntRxFifoOvr++;
119 #endif /*CAN_WITH_STATISTICS*/
121 msgCntlReg = c_can_read_reg_w( pchip, CCIF1DMC );
123 pmsgobj->rx_msg.length = msgCntlReg & 0x000F;
126 pmsgobj->rx_msg.id = (u32)msgid;
128 // Fetch message bytes
129 if (pmsgobj->rx_msg.length > 0)
130 readData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
131 if (pmsgobj->rx_msg.length > 2)
132 readData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
133 if (pmsgobj->rx_msg.length > 4)
134 readData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
135 if (pmsgobj->rx_msg.length > 6)
136 readData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
138 for ( i=0; i < pmsgobj->rx_msg.length; i++ ) {
139 pmsgobj->rx_msg.data[ i ] = readData.bdata[i];
141 DEBUGMSG("(c%dm%d)Received Message:\n",
142 pchip->chip_idx, pmsgobj->object);
143 DEBUGMSG(" id = %d\n",
145 DEBUGMSG(" length = %d\n",
146 pmsgobj->rx_msg.length);
147 for ( i=0; i < pmsgobj->rx_msg.length; i++ )
148 DEBUGMSG(" data[%d] = 0x%.2x\n", i, pmsgobj->rx_msg.data[i]);
150 canque_filter_msg2edges(pmsgobj->qends, &pmsgobj->rx_msg);
152 #ifdef CAN_WITH_STATISTICS
153 // Another received packet
154 pchip->stat.cntRxPkt++;
156 // Add databytes read to statistics block
157 pchip->stat.cntRxData += pmsgobj->rx_msg.length;
158 #endif /*CAN_WITH_STATISTICS*/
160 spin_unlock( &c_can_sprlock );
162 // Check if new data arrived
163 if (c_can_if1_busycheck(pchip)) ;
164 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
165 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
166 if (c_can_if1_busycheck(pchip)) ;
167 if ( !( ( bDataAvail = c_can_read_reg_w( pchip, CCIF1DMC ) ) &
172 if ( bDataAvail & IFXMC_MSGLST ) {
173 CANMSG("(c%dm%d)c-can fifo full: Message lost!\n",
174 pchip->chip_idx, pmsgobj->object);
181 void c_can_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj)
183 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
185 /*if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
186 if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
187 i82527_irq_write_handler(chip, obj);
191 if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
192 i82527_irq_update_filter(chip, obj);
195 /* FIXME: these functionality has to be implemented to start TX */
197 can_msgobj_clear_fl(obj,TX_LOCK);
198 if(can_msgobj_test_fl(obj,TX_REQUEST))
200 if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot)
207 ///////////////////////////////////////////////////////////////////////////////
211 can_irqreturn_t c_can_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
213 struct rtr_id *rtr_search = hardware_p->rtr_queue;
214 struct chip_t *pchip = (struct chip_t *)dev_id;
222 // u32 intCntrVAddr = 0;
224 //unsigned short flags = 0;
226 //if (pchip->ntype != CAN_CHIPTYPE_C_CAN) {
227 // DEBUGMSG("\n(c%d)IRQ not for c_can_irq_handler(...)\n", pchip->chip_idx);
231 irqreg = c_can_read_reg_w( pchip, CCINTR );
234 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx spurious interrupt\n",
236 (long)( pchip->/*v*/base_addr/* + CCSR*/));
240 DEBUGMSG( "\n(c%d)IRQ handler: addr=%.8lx irqreg=0x%.4x\n",
242 (long)( pchip->/*v*/base_addr/* + CCSR*/),
248 c_can_registerdump(pchip);
253 if ( (!( intCntrVAddr = (u32)ioremap( 0x80024000, 0xCD ) ))) {
254 DEBUGMSG("Failed to map Interrupt Controller IO-memory\n");
258 DEBUGMSG( "Mapped Interrupt Controller IO-memory: 0x%lx - 0x%lx to 0x%lx\n",
259 (unsigned long)0X80024000,
260 (unsigned long)0X800240CC,
261 (unsigned long)intCntrVAddr);
264 DEBUGMSG("Current Interrupt Status Register (ISR): 0x%4.4lx\n",
265 (long)readl(intCntrVAddr + 4));
266 DEBUGMSG("Current Interrupt ID: %d\n",
267 (int)(readl(intCntrVAddr + 0x90) & 0xF));
268 iounmap( (void*)intCntrVAddr);
269 DEBUGMSG( "Unmapped Interrupt Controller IO-memory: 0x%lx\n",
270 (unsigned long)intCntrVAddr);
274 // Handle change in status register
276 if ( irqreg == INT_STAT ) {
277 chip_status = c_can_read_reg_w( pchip, CCSR );
278 DEBUGMSG( "(c%d)Status register: 0x%x\n",
279 pchip->chip_idx, chip_status );
281 if ( chip_status & SR_EWARN ) {
282 // There is an abnormal # of errors
283 #ifdef CAN_WITH_STATISTICS
284 pchip->stat.cntWarnings++;
285 #endif /*CAN_WITH_STATISTICS*/
286 errcount = c_can_read_reg_w( pchip, CCEC);
287 DEBUGMSG("(c%d)stat: c_can_irq_handler: Abnormal number of Errors Warning\n"
288 " txErr=%d, rxErr=%d\n",
289 pchip->chip_idx, (errcount&0x00ff), ((errcount&0x7f00)>>8));
292 // this code deactivates the chip if the transmiterrorcounter grew above 127
293 if ((pchip->stat.cntWarnings > 100) && ((errcount&0x00ff) > 127))
295 CANMSG("(c%d)to much Errornumber warnings (>100), deactivating chip",
297 pchip->config_irqs(pchip, 0);
298 pchip->enable_configuration(pchip);
299 pchip->clear_objects(pchip);
300 pchip->flags &= ~CHANNEL_CONFIGURED;
305 if ( chip_status & SR_EPASS ) {
306 // There is an abnormal # of errors
307 #ifdef CAN_WITH_STATISTICS
308 pchip->stat.cntErrPassive++;
309 #endif /*CAN_WITH_STATISTICS*/
310 DEBUGMSG("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
314 if ( chip_status & SR_BOFF ) {
315 // We have a bus off condition
316 #ifdef CAN_WITH_STATISTICS
317 pchip->stat.cntBusOff++;
318 #endif /*CAN_WITH_STATISTICS*/
319 //pchip->fifo->tx_in_progress = 0;
321 CANMSG("(c%d)stat: c_can_irq_handler: Bus Off\n",
323 /*if (pchip->stat.cntBusOff > 100)
325 CANMSG("(c%d)to much busoff warnings (>100), deactivating chip",
327 pchip->config_irqs(pchip, 0);
328 pchip->enable_configuration(pchip);
329 pchip->clear_objects(pchip);
330 pchip->flags &= ~CHANNEL_CONFIGURED;
334 CANMSG("(c%d)try to reconnect",
336 pchip->chipspecops->disable_configuration(pchip);
339 if (chip_status & SR_TXOK) {
340 DEBUGMSG("(c%d)stat: Transmitted a Message successfully\n",
342 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK, CCSR);
345 if (chip_status & SR_RXOK) {
346 DEBUGMSG("(c%d)stat: Received a Message successfully\n",
348 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK, CCSR);
351 #ifdef CAN_WITH_STATISTICS
352 // Errors to statistics
353 switch( chip_status & 0x07 )
355 case SRLEC_NE: // No error
357 case SRLEC_SE: // Stuff error
358 pchip->stat.cntStuffErr++;
360 case SRLEC_FE: // Form error
361 pchip->stat.cntFormErr++;
363 case SRLEC_AE: // Ack error
364 pchip->stat.cntAckErr++;
366 case SRLEC_B1: // Bit 1 error
367 pchip->stat.cntBit1Err++;
369 case SRLEC_B0: // Bit 0 error
370 pchip->stat.cntBit0Err++;
372 case SRLEC_CR: // CRC error
373 pchip->stat.cntCrcErr++;
378 #endif /*CAN_WITH_STATISTICS*/
379 //return; // continue?
381 if (irqreg >0 && irqreg <33) {
382 struct msgobj_t *pmsgobj;
387 pmsgobj=pchip->msgobj[idxobj];
389 //DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",
390 // (unsigned long)pchip->vbase_addr + iIRQ,
391 // (unsigned long)dev_id,
395 spin_lock( &c_can_if1lock );
398 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
399 c_can_write_reg_w(pchip, msgLstReadMaskCM, CCIF1CM);
400 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
402 if (c_can_if1_busycheck(pchip)) ; /*??????????*/
403 tempCntlReg = c_can_read_reg_w( pchip, CCIF1DMC );
405 if (tempCntlReg & IFXMC_MSGLST) {
406 CANMSG("(c%dm%d)Chip lost a message\n",
407 pchip->chip_idx, pmsgobj->object);
408 #ifdef CAN_WITH_STATISTICS
409 pchip->stat.cntMsgLst++;
410 #endif /*CAN_WITH_STATISTICS*/
412 //Reset Message Lost Bit
413 tempCntlReg = tempCntlReg & (~IFXMC_MSGLST);
414 c_can_write_reg_w(pchip, tempCntlReg, CCIF1DMC);
415 c_can_write_reg_w(pchip, msgLstWriteMaskCM, CCIF1CM);
416 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
419 //transfer Message Object to IF1 Buffer
420 if (c_can_if1_busycheck(pchip)) ;
421 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
422 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
424 if (c_can_if1_busycheck(pchip)) ;
425 if (c_can_read_reg_w(pchip, CCIF1A2) & IFXARB2_DIR) {
426 spin_unlock( &c_can_if1lock );
427 c_can_irq_write_handler(pchip,idxobj);
429 if (can_msgobj_test_fl(pmsgobj,RX_MODE_EXT)) {
430 id0=c_can_read_reg_w(pchip, CCIF1A1);
431 id1=(c_can_read_reg_w(pchip, CCIF1A2)&0x1FFF)<<16;
434 msgid=((c_can_read_reg_w(pchip, CCIF1A2)&0x1FFC)>>2)&0x7FF;
436 spin_unlock( &c_can_if1lock );
438 spin_lock(&hardware_p->rtr_lock);
439 while ( rtr_search != NULL )
441 if ( rtr_search->id == msgid ) {
444 rtr_search = rtr_search->next;
446 spin_unlock(&hardware_p->rtr_lock);
448 spin_lock( &c_can_if1lock );
450 //transfer Message Object to IF1 Buffer
451 if (c_can_if1_busycheck(pchip)) ;
452 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
453 c_can_write_reg_w(pchip, idxobj+1, CCIF1CR);
455 if (c_can_if1_busycheck(pchip)) ;
457 if ( ( rtr_search != NULL ) && (rtr_search->id == msgid ) ) {
458 c_can_irq_rtr_handler( pchip, idxobj, msgid );
460 c_can_irq_read_handler( pchip, idxobj, msgid );
462 spin_unlock( &c_can_if1lock );
470 // Get irq status again
471 irqreg = c_can_read_reg_w( pchip, CCINTR );
473 return CAN_IRQ_HANDLED;
476 ///////////////////////////////////////////////////////////////////////////////
477 // c_can_irq_rtr_handler
480 void c_can_irq_rtr_handler( struct chip_t *pchip, int idxobj, u32 msgid )
483 struct rtr_id *prtr_search = hardware_p->rtr_queue;
484 union c_can_data rtrData;
486 spin_lock( &hardware_p->rtr_lock );
488 prtr_search->rtr_message->id = msgid;
489 prtr_search->rtr_message->length =
490 ( c_can_read_reg_w( pchip, CCIF1DMC ) & 0x000f);
492 // Fetch message bytes
493 if (prtr_search->rtr_message->length > 0)
494 rtrData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
495 if (prtr_search->rtr_message->length > 2)
496 rtrData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
497 if (prtr_search->rtr_message->length > 4)
498 rtrData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
499 if (prtr_search->rtr_message->length > 6)
500 rtrData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
502 for ( i=0; i<prtr_search->rtr_message->length; i++ ) {
503 prtr_search->rtr_message->data[ i ] = rtrData.bdata[i];
506 spin_unlock( &hardware_p->rtr_lock );
507 wake_up_interruptible( &prtr_search->rtr_wq );