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 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)
212 ///////////////////////////////////////////////////////////////////////////////
216 int c_can_irq_handler(int irq, struct canchip_t *pchip)
218 struct rtr_id *rtr_search = hardware_p->rtr_queue;
220 int id0 = 0, id1 = 0;
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 */ ),
241 c_can_registerdump(pchip);
245 // Handle change in status register
247 if (irqreg == INT_STAT) {
248 chip_status = c_can_read_reg_w(pchip, CCSR);
249 DEBUGMSG("(c%d)Status register: 0x%x\n",
250 pchip->chip_idx, chip_status);
252 if (chip_status & SR_EWARN) {
253 // There is an abnormal # of errors
254 #ifdef CAN_WITH_STATISTICS
255 pchip->stat.cntWarnings++;
256 #endif /*CAN_WITH_STATISTICS */
257 errcount = c_can_read_reg_w(pchip, CCEC);
259 ("(c%d)stat: c_can_irq_handler: Abnormal number of Errors Warning\n"
260 " txErr=%d, rxErr=%d\n",
261 pchip->chip_idx, (errcount & 0x00ff),
262 ((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 */
284 ("(c%d)stat: c_can_irq_handler: Chip entering Error Passive Mode\n",
288 if (chip_status & SR_BOFF) {
289 // We have a bus off condition
290 #ifdef CAN_WITH_STATISTICS
291 pchip->stat.cntBusOff++;
292 #endif /*CAN_WITH_STATISTICS */
293 //pchip->fifo->tx_in_progress = 0;
296 ("(c%d)stat: c_can_irq_handler: Bus Off\n",
298 /*if (pchip->stat.cntBusOff > 100)
300 CANMSG("(c%d)to much busoff 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;
309 CANMSG("(c%d)try to reconnect",
312 disable_configuration(pchip);
315 if (chip_status & SR_TXOK) {
317 ("(c%d)stat: Transmitted a Message successfully\n",
319 c_can_write_reg_w(pchip, chip_status & ~SR_TXOK,
323 if (chip_status & SR_RXOK) {
325 ("(c%d)stat: Received a Message successfully\n",
327 c_can_write_reg_w(pchip, chip_status & ~SR_RXOK,
330 #ifdef CAN_WITH_STATISTICS
331 // Errors to statistics
332 switch (chip_status & 0x07) {
333 case SRLEC_NE: // No error
335 case SRLEC_SE: // Stuff error
336 pchip->stat.cntStuffErr++;
338 case SRLEC_FE: // Form error
339 pchip->stat.cntFormErr++;
341 case SRLEC_AE: // Ack error
342 pchip->stat.cntAckErr++;
344 case SRLEC_B1: // Bit 1 error
345 pchip->stat.cntBit1Err++;
347 case SRLEC_B0: // Bit 0 error
348 pchip->stat.cntBit0Err++;
350 case SRLEC_CR: // CRC error
351 pchip->stat.cntCrcErr++;
356 #endif /*CAN_WITH_STATISTICS */
357 //return; // continue?
359 if (irqreg > 0 && irqreg < 33) {
360 struct msgobj_t *pmsgobj;
365 pmsgobj = pchip->msgobj[idxobj];
367 //DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",
368 // (unsigned long)pchip->vbase_addr + iIRQ,
369 // (unsigned long)dev_id,
373 spin_lock(&c_can_if1lock);
376 if (c_can_if1_busycheck(pchip)) ; /*?????????? */
377 c_can_write_reg_w(pchip, msgLstReadMaskCM,
379 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
381 if (c_can_if1_busycheck(pchip)) ; /*?????????? */
382 tempCntlReg = c_can_read_reg_w(pchip, CCIF1DMC);
384 if (tempCntlReg & IFXMC_MSGLST) {
385 CANMSG("(c%dm%d)Chip lost a message\n",
388 #ifdef CAN_WITH_STATISTICS
389 pchip->stat.cntMsgLst++;
390 #endif /*CAN_WITH_STATISTICS */
392 //Reset Message Lost Bit
394 tempCntlReg & (~IFXMC_MSGLST);
395 c_can_write_reg_w(pchip, tempCntlReg,
397 c_can_write_reg_w(pchip,
400 c_can_write_reg_w(pchip, idxobj + 1,
403 //transfer Message Object to IF1 Buffer
404 if (c_can_if1_busycheck(pchip)) ;
405 c_can_write_reg_w(pchip, readMaskCM, CCIF1CM);
406 c_can_write_reg_w(pchip, idxobj + 1, CCIF1CR);
408 if (c_can_if1_busycheck(pchip)) ;
409 if (c_can_read_reg_w(pchip, CCIF1A2) &
411 spin_unlock(&c_can_if1lock);
412 c_can_irq_write_handler(pchip, idxobj);
414 if (can_msgobj_test_fl
415 (pmsgobj, RX_MODE_EXT)) {
417 c_can_read_reg_w(pchip,
422 CCIF1A2) & 0x1FFF) << 16;
428 CCIF1A2) & 0x1FFC) >> 2)
431 spin_unlock(&c_can_if1lock);
433 spin_lock(&hardware_p->rtr_lock);
434 while (rtr_search != NULL) {
435 if (rtr_search->id == msgid) {
438 rtr_search = rtr_search->next;
440 spin_unlock(&hardware_p->rtr_lock);
442 spin_lock(&c_can_if1lock);
444 //transfer Message Object to IF1 Buffer
445 if (c_can_if1_busycheck(pchip)) ;
446 c_can_write_reg_w(pchip, readMaskCM,
448 c_can_write_reg_w(pchip, idxobj + 1,
451 if (c_can_if1_busycheck(pchip)) ;
453 if ((rtr_search != NULL)
454 && (rtr_search->id == msgid)) {
455 c_can_irq_rtr_handler(pchip,
459 c_can_irq_read_handler(pchip,
463 spin_unlock(&c_can_if1lock);
471 // Get irq status again
472 irqreg = c_can_read_reg_w(pchip, CCINTR);
474 return CANCHIP_IRQ_HANDLED;
477 ///////////////////////////////////////////////////////////////////////////////
478 // c_can_irq_rtr_handler
481 void c_can_irq_rtr_handler(struct canchip_t *pchip, int idxobj, u32 msgid)
484 struct rtr_id *prtr_search = hardware_p->rtr_queue;
485 union c_can_data rtrData;
487 spin_lock(&hardware_p->rtr_lock);
489 prtr_search->rtr_message->id = msgid;
490 prtr_search->rtr_message->length =
491 (c_can_read_reg_w(pchip, CCIF1DMC) & 0x000f);
493 // Fetch message bytes
494 if (prtr_search->rtr_message->length > 0)
495 rtrData.wdata[0] = c_can_read_reg_w(pchip, CCIF1DA1);
496 if (prtr_search->rtr_message->length > 2)
497 rtrData.wdata[1] = c_can_read_reg_w(pchip, CCIF1DA2);
498 if (prtr_search->rtr_message->length > 4)
499 rtrData.wdata[2] = c_can_read_reg_w(pchip, CCIF1DB1);
500 if (prtr_search->rtr_message->length > 6)
501 rtrData.wdata[3] = c_can_read_reg_w(pchip, CCIF1DB2);
503 for (i = 0; i < prtr_search->rtr_message->length; i++) {
504 prtr_search->rtr_message->data[i] = rtrData.bdata[i];
507 spin_unlock(&hardware_p->rtr_lock);
508 wake_up_interruptible(&prtr_search->rtr_wq);