2 * Linux CAN-bus device driver.
3 * Written by Sergei Sharonov email:sharonov@halliburton.com
4 * sja1000p was used as a prototype
5 * This software is released under the GPL-License.
6 * Version lincan-0.3.2 15 Feb 2006
8 #include "../include/can.h"
9 #include "../include/can_sysdep.h"
10 #include "../include/main.h"
11 #include "../include/mcp2515.h"
15 #define RESET_CMD 0xc0
17 #define WRITE_CMD 0x02
18 #define READ_RX0_CMD 0x90
19 #define READ_RX1_CMD 0x94
20 #define BITMOD_CMD 0x05
22 #define MCP2515_SPI_ASYNC
32 static struct workqueue_struct *mcp2515_wq;
34 static void mcp2515_async_callback(void *data, uint8_t count);
35 static void tx_handler(struct canchip_t *chip, struct msgobj_t *obj);
37 /*****************************************************************************/
38 /* SPI ACCESS FUNCTIONS */
39 /*****************************************************************************/
40 static unsigned char read_reg(struct canchip_t *chip, unsigned addr)
42 uint8_t *command, val;
44 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
45 command[0] = READ_CMD;
47 can_spi_transfer(chip,command,command,3);
51 DEBUGMSG("reg[0x%02x]=>0x%02x\n",addr,(unsigned)val);
56 /*****************************************************************************/
57 static int read_block(struct canchip_t *chip, unsigned startAddr,
58 size_t len, void *data)
62 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
63 memset(command,0,SPI_BUF_LEN);
64 command[0] = READ_CMD;
65 command[1] = startAddr;
66 can_spi_transfer(chip, command, command, len+2);
67 memcpy(data, command+2, len);
72 DEBUGMSG("reg[0x%02x..]=>",startAddr);
73 for(i=0;i<len;i++) DEBUGMSG(" 0x%02x",(unsigned)((uint8_t*)data)[i]);
80 /*****************************************************************************/
81 static void write_reg(struct canchip_t *chip, unsigned addr, unsigned char data)
83 unsigned char *command;
85 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
86 command[0] = WRITE_CMD;
89 can_spi_transfer(chip,command,command,3);
92 DEBUGMSG("reg[0x%02x]<=0x%02x\n",addr,(unsigned)data);
97 /*****************************************************************************/
98 static int write_block(struct canchip_t *chip, unsigned startAddr,
99 size_t len, void *data)
103 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
104 command[0] = WRITE_CMD;
105 command[1] = startAddr;
106 memcpy(command+2,data,len);
107 can_spi_transfer(chip, command, command, len+2);
112 DEBUGMSG("reg[0x%02x..]<=",startAddr);
114 DEBUGMSG(" 0x%02x", (unsigned)((uint8_t*)data)[i]);
122 /*****************************************************************************/
123 static void bitmod_reg(struct canchip_t *chip, unsigned addr,
124 unsigned char mask, unsigned char data)
126 unsigned char *command;
128 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
129 command[0] = BITMOD_CMD;
133 can_spi_transfer(chip,command,command,4);
136 DEBUGMSG("reg[0x%02x]<=0x%02x mask=0x%02x\n",addr,(unsigned)data,(unsigned)mask);
141 /*****************************************************************************/
142 static void bitmod_reg_async(struct canchip_t *chip, unsigned addr,
143 unsigned char mask, unsigned char data, uint8_t opcode)
145 struct can_spi_async_t async;
148 async.opcode = opcode;
149 async.tx_buf[0] = BITMOD_CMD;
150 async.tx_buf[1] = addr;
151 async.tx_buf[2] = mask;
152 async.tx_buf[3] = data;
154 can_spi_async_transfer(chip, mcp2515_async_callback, &async, 1, 0);
157 DEBUGMSG("reg[0x%02x]<=0x%02x mask=0x%02x\n",addr,(unsigned)data,(unsigned)mask);
161 /*****************************************************************************/
162 static void read_async(struct canchip_t *chip, unsigned startAddr, size_t len, uint8_t opcode)
164 struct can_spi_async_t async[2];
166 async[0].chip = chip;
167 async[0].opcode = opcode;
168 async[0].tx_buf[0] = READ_CMD;
169 async[0].tx_buf[1] = startAddr;
170 async[0].len = len+2;
172 if (opcode == READ_CANINTF){
173 async[1].chip = chip;
174 async[1].opcode = opcode;
175 async[1].tx_buf[0] = READ_CMD;
176 async[1].tx_buf[1] = startAddr;
177 async[1].len = len+2;
178 can_spi_async_transfer(chip, mcp2515_async_callback, async, 2, 1);
181 can_spi_async_transfer(chip, mcp2515_async_callback, async, 1, 0);
184 /*****************************************************************************/
185 inline void read_rx_async(struct canchip_t *chip, unsigned rxbuf,struct msgobj_t *obj)
187 struct can_spi_async_t async = {
189 .opcode = rxbuf?READ_RX1:READ_RX0,
190 .tx_buf[0] = rxbuf?READ_RX1_CMD:READ_RX0_CMD,
191 .len = sizeof(MCP2515_FRAME)+1,
195 can_spi_async_transfer(chip, mcp2515_async_callback, &async, 1, 0);
198 /*****************************************************************************/
199 inline void read_err_async(struct canchip_t *chip)
201 struct can_spi_async_t async;
204 async.opcode = READ_ERR;
205 async.tx_buf[0] = READ_CMD;
206 async.tx_buf[1] = MCP2515_EFLG;
209 can_spi_async_transfer(chip, mcp2515_async_callback, &async, 1, 0);
212 /*****************************************************************************/
213 static void txwq_handler(struct work_struct *work)
215 MCP2515_PRIV *priv = container_of(work,MCP2515_PRIV,txwq_handler);
216 struct canchip_t *chip = priv->chip;
220 n = find_first_bit(priv->txfree, MCP2515_TXBUF_NUM);
221 while (n<MCP2515_TXBUF_NUM){
222 clear_bit(n,priv->txfree);
223 tx_handler(chip,chip->msgobj[n]);
224 n = find_first_bit(priv->txfree, MCP2515_TXBUF_NUM);
229 static int mcp2515_async_canintf_reread = 0;
230 /*****************************************************************************/
231 static void mcp2515_async_callback(void *data,uint8_t count){
232 struct can_spi_async_t *async = (struct can_spi_async_t *)data;
233 struct canchip_t *chip;
234 struct msgobj_t *obj;
239 for (i=0;i<count;i++){
240 switch (async[i].opcode){
245 MCP2515_FRAME *frame = NULL;
247 chip = async[i].chip;
248 if (chip == NULL) return;
250 if (obj == NULL) return;
252 if (async[i].rx_buf == NULL)
253 panic("async[%d].rx_buf is null",i);
254 frame = (MCP2515_FRAME *)(async[i].rx_buf+1); //The received data is 1 byte late
256 if(frame->sidl & mcpIDE) {
257 DEBUGMSG("extended frame\n");
259 ((uint32_t)frame->eid0) |
260 ((uint32_t)frame->eid8) << 8 |
261 ((uint32_t)frame->sidl & 0x03) << 16 |
262 ((uint32_t)frame->sidl & 0xe0) << 13 |
263 ((uint32_t)frame->sidh) << 21;
264 obj->rx_msg.flags = MSG_EXT | ((frame->dlc & mcpRTR) ? MSG_RTR : 0);
267 DEBUGMSG("standard frame\n");
269 ((uint32_t)frame->sidl) >> 5 |
270 ((uint32_t)frame->sidh) << 3;
271 obj->rx_msg.flags = ((frame->sidl & mcpSRR) ? MSG_RTR : 0);
274 len = frame->dlc & mcpDLC_MASK;
275 if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
276 obj->rx_msg.length = len;
278 memcpy(obj->rx_msg.data,frame->data,len);
280 /* fill CAN message timestamp */
281 // can_filltimestamp(&obj->rx_msg.timestamp);
282 memcpy(&obj->rx_msg.timestamp, &async->timestamp, sizeof(canmsg_tstamp_t));
283 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
286 case READ_CANINTF : {
287 uint8_t flags = async[i].rx_buf[2];
290 chip = async[i].chip;
291 if (chip == NULL) break;
292 priv=(MCP2515_PRIV *)(chip->chip_data);
293 if (priv == NULL) break;
295 if ((count > i+1) && (async[i+1].opcode == READ_CANINTF) && (async[++i].rx_buf[2] ^ flags)){
296 DEBUGMSG("Found differences in two consequent interrupt flag readings. Reading again...\n");
297 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
301 if((flags == 0) && (mcp2515_async_canintf_reread)){
302 mcp2515_async_canintf_reread = 0;
303 enable_irq(chip->chip_irq);
306 else if((flags == 0)){
307 mcp2515_async_canintf_reread++;
308 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
311 mcp2515_async_canintf_reread = 0;
313 DEBUGMSG("mcp251x_irq_work_handler:%s%s%s%s%s%s%s%s\n",
314 (flags & mcpRX0INT) ? " RX0":"",
315 (flags & mcpRX1INT) ? " RX1":"",
316 (flags & mcpTX0INT) ? " TX0":"",
317 (flags & mcpTX1INT) ? " TX1":"",
318 (flags & mcpTX2INT) ? " TX2":"",
319 (flags & mcpERRINT) ? " ERR":"",
320 (flags & mcpWAKINT) ? " WAK":"",
321 (flags & mcpMERREINT) ? " MERRE":"");
324 if(flags & mcpRX0INT) read_rx_async(chip,0,chip->msgobj[0]);
325 if(flags & mcpRX1INT) read_rx_async(chip,1,chip->msgobj[0]);
326 if(flags & mcpTX0INT) {
327 set_bit(0,priv->txfree);
328 queue_work(mcp2515_wq,&priv->txwq_handler);
330 if(flags & mcpTX1INT) {
331 set_bit(1,priv->txfree);
332 queue_work(mcp2515_wq,&priv->txwq_handler);
334 if(flags & mcpTX2INT) {
335 set_bit(2,priv->txfree);
336 queue_work(mcp2515_wq,&priv->txwq_handler);
339 if(flags & mcpERRINT) read_err_async(chip);
340 if(flags & mcpMERREINT) (priv->errcnt.merre)++;
341 if(flags & mcpWAKINT) (priv->wakeint_cnt)++;
343 bitmod_reg_async(chip, MCP2515_CANINTF, flags & ~(mcpRX0INT|mcpRX1INT), 0, NOOP);
345 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
349 uint8_t error = async[i].rx_buf[2];
352 chip = async[i].chip;
353 if (chip == NULL) break;
354 priv=(MCP2515_PRIV *)(chip->chip_data);
355 if (priv == NULL) break;
357 if(error & mcpRX0OVR) {
358 (priv->errcnt.rx0ovr)++;
359 CANMSG("can: RX0OVR\n");
361 if(error & mcpRX1OVR) (priv->errcnt.rx1ovr)++;
362 if(error & mcpTXBO) (priv->errcnt.txbo)++;
363 if(error & mcpTXEP) (priv->errcnt.txep)++;
364 if(error & mcpRXEP) (priv->errcnt.rxep)++;
365 if(error & mcpTXWAR) (priv->errcnt.txwar)++;
366 if(error & mcpRXWAR) (priv->errcnt.rxwar)++;
367 if(error & mcpEWARN) (priv->errcnt.ewarn)++;
371 default : CANMSG("OMAP2_SPICAN got unknown asynchronous response");
376 /*****************************************************************************/
378 /*****************************************************************************/
379 int mcp2515_get_info(struct canchip_t *chip, char *buf)
381 MCP2515_PRIV *priv=(MCP2515_PRIV *)(chip->chip_data);
385 can_spi_acquire_bus(chip, 1);
386 opmode = read_reg(chip,MCP2515_CANSTAT) & mcpMOD_MASK;
387 can_spi_release_bus(chip);
388 len += sprintf(buf+len,"opmode : %s%s%s%s%s\n",
389 (opmode == mcpMOD_NORM) ? "norm" : "",
390 (opmode == mcpMOD_SLEEP) ? "sleep" : "",
391 (opmode == mcpMOD_LOOPBACK) ? "loopback" : "",
392 (opmode == mcpMOD_LISTEN) ? "listen" : "",
393 (opmode == mcpMOD_CONFIG) ? "config" : "");
395 len += sprintf(buf+len,"spi ch : %d\n",chip->spi_channel);
396 len += sprintf(buf+len,"rx0ovr : %u\n",priv->errcnt.rx0ovr);
397 len += sprintf(buf+len,"rx1ovr : %u\n",priv->errcnt.rx1ovr);
398 len += sprintf(buf+len,"txbo : %u\n",priv->errcnt.txbo);
399 len += sprintf(buf+len,"txep : %u\n",priv->errcnt.txep);
400 len += sprintf(buf+len,"rxep : %u\n",priv->errcnt.rxep);
401 len += sprintf(buf+len,"txwar : %u\n",priv->errcnt.txwar);
402 len += sprintf(buf+len,"rxwar : %u\n",priv->errcnt.rxwar);
403 len += sprintf(buf+len,"ewarn : %u\n",priv->errcnt.ewarn);
404 len += sprintf(buf+len,"merre : %u\n",priv->errcnt.merre);
405 len += sprintf(buf+len,"wakeup : %u\n",priv->wakeint_cnt);
411 /*****************************************************************************/
413 /*****************************************************************************/
414 static void rx_handler(struct canchip_t *chip, int bufNo, struct msgobj_t *obj)
419 if(chip == NULL) panic("rx_handler: chip==NULL");
420 if(obj == NULL) panic("rx_handler: obj==NULL");
422 /* get all frame data */
424 read_block(chip,MCP2515_RXB0SIDH,sizeof(MCP2515_FRAME),&frame);
425 bitmod_reg(chip,MCP2515_CANINTF, mcpRX0INT, ~mcpRX0INT);
428 read_block(chip,MCP2515_RXB1SIDH,sizeof(MCP2515_FRAME),&frame);
429 bitmod_reg(chip,MCP2515_CANINTF, mcpRX1INT, ~mcpRX1INT);
432 if(frame.sidl & mcpIDE) {
433 DEBUGMSG("extended frame\n");
435 ((uint32_t)frame.sidl & 0xe0) >> 5 |
436 ((uint32_t)frame.sidh) << 3 |
437 ((uint32_t)frame.eid0) << 11 |
438 ((uint32_t)frame.eid8) << 19 |
439 ((uint32_t)frame.sidl & 0x03) << 27;
440 obj->rx_msg.flags = MSG_EXT | ((frame.dlc & mcpRTR) ? MSG_RTR : 0);
443 DEBUGMSG("standard frame\n");
445 ((uint32_t)frame.sidl & 0xe0) >> 5 |
446 ((uint32_t)frame.sidh) << 3;
447 obj->rx_msg.flags = ((frame.sidl & mcpSRR) ? MSG_RTR : 0);
450 len = frame.dlc & mcpDLC_MASK;
451 if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
452 obj->rx_msg.length = len;
454 memcpy(obj->rx_msg.data,frame.data,len);
456 /* fill CAN message timestamp */
457 can_filltimestamp(&obj->rx_msg.timestamp);
458 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
461 /*****************************************************************************/
462 static void tx_handler(struct canchip_t *chip, struct msgobj_t *obj)
466 if(chip == NULL) panic("tx_handler: chip==NULL");
467 if(obj == NULL) panic("tx_handler: obj==NULL");
468 #ifndef MCP2515_SPI_ASYNC
469 bitmod_reg(chip,MCP2515_CANINTF, mcpTX0INT, ~mcpTX0INT);
473 /* Do local transmitted message distribution if enabled */
475 /* fill CAN message timestamp */
476 can_filltimestamp(&obj->tx_slot->msg.timestamp);
478 obj->tx_slot->msg.flags |= MSG_LOCAL;
479 canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
481 /* Free transmitted slot */
482 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
486 can_msgobj_clear_fl(obj,TX_PENDING);
487 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
490 can_msgobj_set_fl(obj,TX_PENDING);
492 if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
494 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
495 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
499 if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
501 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
502 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
509 /*****************************************************************************/
510 static void errint_handler(struct canchip_t *chip)
513 MCP2515_PRIV *priv=(MCP2515_PRIV *)(chip->chip_data);
515 error = read_reg(chip, MCP2515_EFLG);
516 bitmod_reg(chip,MCP2515_CANINTF, mcpERRINT, ~mcpERRINT);
519 if(error & mcpRX0OVR) {
520 (priv->errcnt.rx0ovr)++;
521 CANMSG("can: RX0OVR\n");
523 if(error & mcpRX1OVR) (priv->errcnt.rx1ovr)++;
524 if(error & mcpTXBO) (priv->errcnt.txbo)++;
525 if(error & mcpTXEP) (priv->errcnt.txep)++;
526 if(error & mcpRXEP) (priv->errcnt.rxep)++;
527 if(error & mcpTXWAR) (priv->errcnt.txwar)++;
528 if(error & mcpRXWAR) (priv->errcnt.rxwar)++;
529 if(error & mcpEWARN) (priv->errcnt.ewarn)++;
532 /*****************************************************************************/
533 static void irq_work(void *data)
535 struct canchip_t *chip=(struct canchip_t *)data;
541 priv=(MCP2515_PRIV *)(chip->chip_data);
545 #ifdef MCP2515_SPI_ASYNC
546 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
550 flags = read_reg(chip, MCP2515_CANINTF);
551 if(flags == 0) break;
552 DEBUGMSG("mcp251x_irq_work_handler:%s%s%s%s%s%s%s%s\n",
553 (flags & mcpRX0INT) ? " RX0":"",
554 (flags & mcpRX1INT) ? " RX1":"",
555 (flags & mcpTX0INT) ? " TX0":"",
556 (flags & mcpTX1INT) ? " TX1":"",
557 (flags & mcpTX2INT) ? " TX2":"",
558 (flags & mcpERRINT) ? " ERR":"",
559 (flags & mcpWAKINT) ? " WAK":"",
560 (flags & mcpMERREINT) ? " MERRE":"");
562 if(flags & mcpRX0INT) rx_handler(chip,0,chip->msgobj[0]);
563 if(flags & mcpRX1INT) rx_handler(chip,1,chip->msgobj[0]);
564 if(flags & mcpTX0INT) tx_handler(chip,chip->msgobj[0]);
565 if(flags & mcpTX1INT) tx_handler(chip,chip->msgobj[1]);
566 if(flags & mcpTX2INT) tx_handler(chip,chip->msgobj[2]);
567 if(flags & mcpERRINT) errint_handler(chip);
569 if(flags & mcpMERREINT){
570 bitmod_reg(chip,MCP2515_CANINTF, mcpMERREINT, ~mcpMERREINT);
571 (priv->errcnt.merre)++;
573 if(flags & mcpWAKINT) (priv->wakeint_cnt)++;
575 // bitmod_reg(chip, MCP2515_CANINTF, flags, 0);
577 enable_irq(chip->chip_irq);
578 #endif /* MCP2515_SPI_ASYNC */
581 /*****************************************************************************/
583 static void tasklet_handler(unsigned long data)
585 struct canchip_t *chip=(struct canchip_t *)data;
589 /* Already acquired bus, go do work */
591 can_spi_release_bus(chip);
594 /*****************************************************************************/
595 static void workqueue_handler(struct work_struct *work)
597 MCP2515_PRIV *priv = container_of(work,MCP2515_PRIV,workqueue_handler);
598 struct canchip_t *chip = priv->chip;
601 can_spi_acquire_bus(chip, 1);
603 can_spi_release_bus(chip);
606 /*****************************************************************************/
607 /* EXPORT FUNCTIONS */
608 /*****************************************************************************/
609 int mcp2515_reset_chip(struct canchip_t *chip)
611 unsigned char *command;
613 DEBUGMSG("reset chip\n");
615 command = ((MCP2515_PRIV*)(chip->chip_data))->spi_buf;
616 command[0] = RESET_CMD;
617 can_spi_acquire_bus(chip,1);
618 can_spi_transfer(chip,command,command,1);
619 can_spi_release_bus(chip);
622 DEBUGMSG("reset mcp2515:%d\n",chip->chip_idx);
628 * mcp2515_enable_configuration - enable chip configuration mode
629 * @chip: pointer to chip state structure
631 int mcp2515_enable_configuration(struct canchip_t *chip)
634 enum mcp2515_MOD stat;
636 DEBUGMSG("mcp2515_enable_configuration\n");
638 can_disable_irq(chip->chip_irq);
640 can_spi_acquire_bus(chip,1);
642 bitmod_reg(chip, MCP2515_CANCTRL, mcpMOD_MASK, mcpMOD_CONFIG);
643 stat = read_reg(chip,MCP2515_CANSTAT);
644 if((stat & mcpMOD_MASK) == mcpMOD_CONFIG) {
645 can_spi_release_bus(chip);
650 can_spi_release_bus(chip);
652 CANMSG("Failed to set cfg mode\n");
653 can_enable_irq(chip->chip_irq);
658 * mcp2515_disable_configuration - disable chip configuration mode
659 * @chip: pointer to chip state structure
661 int mcp2515_disable_configuration(struct canchip_t *chip)
664 enum mcp2515_MOD stat;
666 DEBUGMSG("mcp2515_disable_configuration\n");
668 can_spi_acquire_bus(chip,1);
670 bitmod_reg(chip, MCP2515_CANCTRL, mcpMOD_MASK, mcpMOD_NORM);
671 stat = read_reg(chip,MCP2515_CANSTAT);
672 if((stat & mcpMOD_MASK) == mcpMOD_NORM) {
673 can_enable_irq(chip->chip_irq);
674 can_spi_release_bus(chip);
679 can_spi_release_bus(chip);
681 CANMSG("Failed to set normal mode\n");
687 * mcp2515_chip_config: - can chip configuration
688 * @chip: pointer to chip state structure
690 * This function configures chip and prepares it for message
691 * transmission and reception. The function resets chip,
692 * resets mask for acceptance of all messages by call to
693 * mcp2515_extended_mask() function and then
694 * computes and sets baudrate with use of function mcp2515_baud_rate().
695 * Return Value: negative value reports error.
696 * File: src/mcp2515.c
698 int mcp2515_chip_config(struct canchip_t *chip)
700 uint8_t pat0[8]={0x00,0xff,0xaa,0x55,0x0f,0xf0,0x3c,0xc3};
704 DEBUGMSG("mcp2515_chip_config\n");
706 ((MCP2515_PRIV *)(chip->chip_data))->chip = chip;
708 if (mcp2515_enable_configuration(chip))
711 /* Acquire SPI bus */
712 can_spi_acquire_bus(chip,1);
714 /* Set TXnRTS pins as digital inputs */
715 write_reg(chip,MCP2515_TXRTSCTRL,0);
717 /* Set RXnBF pins as digital outputs, b0=low, b1=high */
718 write_reg(chip, MCP2515_BFPCTRL,
719 mcpB0BFE | mcpB1BFE | /* mcpB0BFS | */ mcpB1BFS);
721 /* Ensure, that interrupts are disabled even on the chip level now */
722 write_reg(chip, MCP2515_CANINTE, 0);
724 /* Configure second receive buffer for rollover */
725 bitmod_reg(chip, MCP2515_RXB0CTRL, mcpBUKT, mcpBUKT);
728 /* Simple check for chip presence */
730 write_block(chip,MCP2515_TXB0DATA,8,pat0);
732 read_block(chip,MCP2515_TXB0DATA,8,pat1);
734 if(memcmp(pat0,pat1,8)) {
735 CANMSG("mcp2515_chip_config: chip #%d not found\n",
737 CANMSG("Requested: Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X\n",pat0[0],pat0[1],pat0[2],pat0[3],pat0[4],pat0[5],pat0[6],pat0[7]);
738 CANMSG("Obtained : Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X Ox%X\n",pat1[0],pat1[1],pat1[2],pat1[3],pat1[4],pat1[5],pat1[6],pat1[7]);
746 can_spi_release_bus(chip);
748 CANMSG("Found mcp2515:%d\n",chip->chip_idx);
751 // Accept only most the dominant message
752 if (mcp2515_extended_mask(chip,0xffffffff, 0xffffffff))
754 /* // Accept only most the dominant message
755 if (mcp2515_extended_mask(chip,0xffffffff, 0x00000000))
758 if (!chip->baudrate) chip->baudrate=1000000;
759 if (mcp2515_baud_rate(chip,chip->baudrate,chip->clock,0,75,0))
762 /* Enable hardware interrupts */
763 can_spi_acquire_bus(chip,1);
764 write_reg(chip, MCP2515_CANINTE, 0xff);
765 can_spi_release_bus(chip);
767 mcp2515_disable_configuration(chip);
772 * mcp2515_extended_mask: - setup of extended mask for message filtering
773 * @chip: pointer to chip state structure
774 * @code: can message acceptance code
775 * @mask: can message acceptance mask
777 * Return Value: negative value reports error.
778 * File: src/mcp2515.c
780 int mcp2515_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
782 char c_filter[4],c_mask[4];
783 DEBUGMSG("mcp2515_extended_mask\n");
786 if (mcp2515_enable_configuration(chip))
789 c_filter[0] = (code >> 3) & 0xFF;
790 c_filter[1] = ((code << 5) & 0xE0 ) | 1<<3 | ((code >> 16) & 0x03);
791 c_filter[2] = (code >> 8) & 0xFF;
792 c_filter[3] = (code) & 0xFF;
793 write_block(chip, MCP2515_RXF0SIDH, 4, c_filter);
794 write_block(chip, MCP2515_RXF2SIDH, 4, c_filter);
795 write_block(chip, MCP2515_RXF3SIDH, 4, c_filter);
796 write_block(chip, MCP2515_RXF4SIDH, 4, c_filter);
797 write_block(chip, MCP2515_RXF5SIDH, 4, c_filter);
798 c_filter[1] = ((code << 5) & 0xE0 ) | 0<<3 | ((code >> 16) & 0x03);
799 write_block(chip, MCP2515_RXF1SIDH, 4, c_filter);
800 c_mask[0] = (mask >> 3) & 0xFF;
801 c_mask[1] = ((mask << 5) & 0xE0 ) | ((mask >> 16) & 0x03);
802 c_mask[2] = (mask >> 8) & 0xFF;
803 c_mask[3] = (mask) & 0xFF;
804 write_block(chip, MCP2515_RXM0SIDH, 4, c_mask);
805 write_block(chip, MCP2515_RXM1SIDH, 4, c_mask);
807 CANMSG("Setting acceptance code to 0x%lx\n",(unsigned long)code);
808 CANMSG("Setting acceptance mask to 0x%lx\n",(unsigned long)mask);
809 // DEBUGMSG("Setting acceptance code to 0x%lx\n",(unsigned long)code);
810 // DEBUGMSG("Setting acceptance mask to 0x%lx\n",(unsigned long)mask);
812 mcp2515_disable_configuration(chip);
818 * mcp2515_baud_rate: - set communication parameters.
819 * @chip: pointer to chip state structure
820 * @rate: baud rate in Hz
821 * @clock: frequency of mcp2515 clock in Hz (ISA osc is 14318000)
822 * @sjw: synchronization jump width (0-3) prescaled clock cycles
823 * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
824 * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
826 * Return Value: negative value reports error.
827 * File: src/mcp2515.c
829 int mcp2515_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw_in,
830 int sampl_pt, int flags)
832 int tqs; /* tbit/TQ */
834 int ps1, ps2, propseg, sjw;
838 DEBUGMSG("mcp2515_baud_rate\n");
839 DEBUGMSG("Clock = %d, rate = %d\n",clock,rate);
841 /* Determine the BRP value that gives the requested bit rate. */
842 for(brp = 0; brp < 8; brp++) {
843 tqs = clock / (2 * (brp + 1)) / rate;
844 if (tqs >= 5 && tqs <= 25
845 && (clock / (2 * (brp + 1)) / tqs) == rate)
851 /* The CAN bus bit time (tbit) is determined by:
852 * tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ
855 * sample point (between PS1 and PS2) must be at 60%-70% of the bit time
856 * PropSeg + PS1 >= PS2
857 * PropSeg + PS1 >= Tdelay
859 * 1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8
860 * SJW = 1 is sufficient in most cases.
861 * Tdelay is usually 1 or 2 TQ.
864 propseg = ps1 = ps2 = (tqs - 1) / 3;
865 if (tqs - (1 + propseg + ps1 + ps2) == 2)
867 if (tqs - (1 + propseg + ps1 + ps2) == 1)
871 DEBUGMSG("bit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n",
872 brp, tqs, propseg, ps1, ps2, sjw);
874 if (mcp2515_enable_configuration(chip))
877 #define CNF2_BTLMODE 0x80
878 #define CNF3_PHSEG2_MASK 0x07
880 can_spi_acquire_bus(chip,1);
882 write_reg(chip, MCP2515_CNF1, ((sjw-1) << 6) | brp);
883 write_reg(chip, MCP2515_CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1));
884 bitmod_reg(chip, MCP2515_CNF3, CNF3_PHSEG2_MASK,(ps2-1));
886 readreg = read_reg(chip, MCP2515_CNF1);
887 if (readreg != (u8)(((sjw-1) << 6) | brp)){
888 CANMSG("Wrong value in CNF1 - sent: 0x%X, received: 0x%X\n",((sjw-1) << 6) | brp,readreg);
891 readreg = read_reg(chip, MCP2515_CNF2);
892 if (readreg != (u8)(CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1))){
893 CANMSG("Wrong value in CNF2 - sent: 0x%X, received: 0x%X\n",CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1),readreg);
896 readreg = read_reg(chip, MCP2515_CNF3);
897 if ((readreg & CNF3_PHSEG2_MASK) != (u8)((ps2-1))){
898 CANMSG("Wrong value in CNF3 - sent: 0x%X, received: 0x%X\n",(ps2-1) | brp,readreg & CNF3_PHSEG2_MASK);
903 can_spi_release_bus(chip);
905 CANMSG("Failed to set bit rate for %d times\n",i);
906 mcp2515_disable_configuration(chip);
910 /* Calculate actual bit rate. */
911 DEBUGMSG("actual bit rate=%u\n",clock / (2 * (brp + 1)) / tqs);
913 mcp2515_disable_configuration(chip);
919 * mcp2515_pre_read_config: - prepares message object for message reception
920 * @chip: pointer to chip state structure
921 * @obj: pointer to message object state structure
923 * Return Value: negative value reports error.
924 * Positive value indicates immediate reception of message.
925 * File: src/mcp2515.c
927 int mcp2515_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
929 DEBUGMSG("mcp2515_pre_read_config\n");
931 /* FIXME - error recovery here */
936 #define MAX_TRANSMIT_WAIT_LOOPS 20
938 * mcp2515_pre_write_config: - prepares message object for message transmission
939 * @chip: pointer to chip state structure
940 * @obj: pointer to message object state structure
941 * @msg: pointer to CAN message
943 * This function prepares selected message object for future initiation
944 * of message transmission by mcp2515_send_msg() function.
945 * The CAN message data and message ID are transfered from @msg slot
946 * into chip buffer in this function.
947 * Return Value: negative value reports error.
948 * File: src/mcp2515.c
950 int mcp2515_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
951 struct canmsg_t *msg)
958 DEBUGMSG("mcp2515_pre_write_config: id=%u len=%u\n",
960 (unsigned)msg->length);
962 can_spi_acquire_bus(chip,1);
964 /* Wait until Transmit Buffer Status is released */
966 busy = read_reg(chip, MCP2515_TXB0CTRL) & mcpTXREQ;
969 } while (i < MAX_TRANSMIT_WAIT_LOOPS);
972 /* FIXME - error recovery here */
975 CANMSG("Transmit timed out, cancelling\n");
976 bitmod_reg(chip, MCP2515_TXB0CTRL, mcpTXREQ, 0);
977 can_spi_release_bus(chip);
982 if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
984 if(msg->flags & MSG_EXT) {
985 frame.sidh = (msg->id >> 3) & 0xFF;
986 frame.sidl = ((msg->id << 5) | ((msg->id >> 27) & mcpEID_MASK) | mcpEXIDE) & 0xFF;
987 frame.eid8 = (msg->id >> 19) & 0xFF;
988 frame.eid0 = (msg->id >> 11) & 0xFF;
989 frame.dlc = len | ((msg->flags & MSG_RTR) ? mcpRTR : 0);
990 memcpy(frame.data, msg->data, len);
993 frame.sidh = (msg->id >> 3) & 0xFF;
994 frame.sidl = ((msg->id << 5) | ((msg->id >> 27) & mcpEID_MASK)) & 0xFF;
995 frame.eid8 = (msg->id >> 19) & 0xFF;
996 frame.eid0 = (msg->id >> 11) & 0xFF;
997 frame.dlc = len | ((msg->flags & MSG_RTR) ? mcpRTR : 0);
998 memcpy(frame.data, msg->data, len);
1001 if (obj == chip->msgobj[0])
1002 write_block(chip, MCP2515_TXB0SIDH, len+5, &frame);
1003 if (obj == chip->msgobj[1])
1004 write_block(chip, MCP2515_TXB1SIDH, len+5, &frame);
1005 if (obj == chip->msgobj[2])
1006 write_block(chip, MCP2515_TXB2SIDH, len+5, &frame);
1008 can_spi_release_bus(chip);
1014 * mcp2515_send_msg: - initiate message transmission
1015 * @chip: pointer to chip state structure
1016 * @obj: pointer to message object state structure
1017 * @msg: pointer to CAN message
1019 * This function is called after mcp2515_pre_write_config() function,
1020 * which prepares data in chip buffer.
1021 * Return Value: negative value reports error.
1022 * File: src/mcp2515.c
1024 int mcp2515_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
1025 struct canmsg_t *msg)
1027 DEBUGMSG("mcp2515_send_msg\n");
1029 can_spi_acquire_bus(chip,1);
1030 #ifdef MCP2515_SPI_ASYNC
1031 if (obj == chip->msgobj[0])
1032 bitmod_reg_async(chip, MCP2515_TXB0CTRL, mcpTXREQ, mcpTXREQ, NOOP);
1033 if (obj == chip->msgobj[1])
1034 bitmod_reg_async(chip, MCP2515_TXB1CTRL, mcpTXREQ, mcpTXREQ, NOOP);
1035 if (obj == chip->msgobj[2])
1036 bitmod_reg_async(chip, MCP2515_TXB2CTRL, mcpTXREQ, mcpTXREQ, NOOP);
1038 if (obj == chip->msgobj[0])
1039 bitmod_reg(chip, MCP2515_TXB0CTRL, mcpTXREQ, mcpTXREQ);
1040 if (obj == chip->msgobj[1])
1041 bitmod_reg(chip, MCP2515_TXB1CTRL, mcpTXREQ, mcpTXREQ);
1042 if (obj == chip->msgobj[2])
1043 bitmod_reg(chip, MCP2515_TXB2CTRL, mcpTXREQ, mcpTXREQ);
1045 can_spi_release_bus(chip);
1051 * mcp2515_check_tx_stat: - checks state of transmission engine
1052 * @chip: pointer to chip state structure
1054 * Return Value: negative value reports error.
1055 * Positive return value indicates transmission under way status.
1056 * Zero value indicates finishing of all issued transmission requests.
1057 * File: src/mcp2515.c
1059 int mcp2515_check_tx_stat(struct canchip_t *chip)
1062 DEBUGMSG("mcp2515_check_tx_stat\n");
1064 can_spi_acquire_bus(chip,1);
1065 status = read_reg(chip,MCP2515_TXB0CTRL) & mcpTXREQ;
1066 can_spi_release_bus(chip);
1068 if (status) return 1;
1073 * mcp2515_set_btregs: - configures bitrate registers
1074 * @chip: pointer to chip state structure
1075 * @btr0: bitrate register 0
1076 * @btr1: bitrate register 1
1078 * Return Value: negative value reports error.
1079 * File: src/mcp2515.c
1081 int mcp2515_set_btregs(struct canchip_t *chip, unsigned short btr0,
1082 unsigned short btr1)
1084 DEBUGMSG("mcp2515_set_btregs\n");
1086 if (mcp2515_enable_configuration(chip))
1089 can_write_reg(chip, btr0, SJABTR0);
1090 can_write_reg(chip, btr1, SJABTR1);
1092 mcp2515_disable_configuration(chip);
1098 * mcp2515_start_chip: - starts chip message processing
1099 * @chip: pointer to chip state structure
1101 * Return Value: negative value reports error.
1102 * File: src/mcp2515.c
1104 int mcp2515_start_chip(struct canchip_t *chip)
1106 MCP2515_PRIV *priv=(MCP2515_PRIV *)(chip->chip_data);
1107 DEBUGMSG("mcp2515_start_chip\n");
1109 can_spi_acquire_bus(chip,1);
1110 bitmod_reg(chip, MCP2515_CANCTRL, mcpMOD_MASK, mcpMOD_NORM);
1111 can_spi_release_bus(chip);
1113 /* reset error counters */
1114 memset(&(priv->errcnt),0,sizeof(MCP2515_ERRCNT));
1120 * mcp2515_stop_chip: - stops chip message processing
1121 * @chip: pointer to chip state structure
1123 * Return Value: negative value reports error.
1124 * File: src/mcp2515.c
1126 int mcp2515_stop_chip(struct canchip_t *chip)
1128 DEBUGMSG("mcp2515_stop_chip\n");
1130 can_spi_acquire_bus(chip,1);
1131 bitmod_reg(chip, MCP2515_CANCTRL, mcpMOD_MASK, mcpMOD_SLEEP);
1132 can_spi_release_bus(chip);
1138 * mcp2515_attach_to_chip: - attaches to the chip, setups registers and state
1139 * @chip: pointer to chip state structure
1141 * Return Value: negative value reports error.
1142 * File: src/mcp2515.c
1144 int mcp2515_attach_to_chip(struct canchip_t *chip)
1146 DEBUGMSG("mcp2515_attach_to_chip\n");
1147 /* Initialize delayed interrupt processing */
1148 mcp2515_wq = create_singlethread_workqueue("lincan_mcp2515");
1149 if (mcp2515_wq == NULL)
1152 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
1153 INIT_WORK(&(((MCP2515_PRIV *)(chip->chip_data))->workqueue_handler),
1155 &(((MCP2515_PRIV *)(chip->chip_data))->workqueue_handler);
1156 INIT_WORK(&(((MCP2515_PRIV *)(chip->chip_data))->txwq_handler),
1158 &(((MCP2515_PRIV *)(chip->chip_data))->txwq_handler);
1160 INIT_WORK(&(((MCP2515_PRIV *)(chip->chip_data))->workqueue_handler),
1162 INIT_WORK(&(((MCP2515_PRIV *)(chip->chip_data))->txwq_handler),
1166 tasklet_init(&(((MCP2515_PRIV *)(chip->chip_data))->tasklet_handler),
1168 (unsigned long)chip);
1174 * mcp2515_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
1175 * @chip: pointer to chip state structure
1177 * Return Value: negative value reports error.
1178 * File: src/mcp2515.c
1180 int mcp2515_release_chip(struct canchip_t *chip)
1182 DEBUGMSG("mcp2515_release_chip\n");
1184 panic("release: chip == NULL");
1185 if (chip->chip_data==NULL)
1186 panic("release: chip_data == NULL");
1188 chip->flags &= ~CHIP_ATTACHED;
1189 DEBUGMSG("Flush workqueue.\n");
1190 cancel_delayed_work(&((MCP2515_PRIV *)(chip->chip_data))->txwq_handler);
1191 cancel_delayed_work(&((MCP2515_PRIV *)(chip->chip_data))->workqueue_handler);
1192 flush_workqueue(mcp2515_wq);
1194 DEBUGMSG("Kill tasklets.\n");
1195 tasklet_kill(&((MCP2515_PRIV *)(chip->chip_data))->tasklet_handler);
1197 mcp2515_stop_chip(chip);
1198 can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
1200 destroy_workqueue(mcp2515_wq);
1206 * mcp2515_remote_request: - configures message object and asks for RTR message
1207 * @chip: pointer to chip state structure
1208 * @obj: pointer to message object structure
1210 * Return Value: negative value reports error.
1211 * File: src/mcp2515.c
1213 int mcp2515_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
1215 CANMSG("mcp2515_remote_request not implemented\n");
1220 * mcp2515_standard_mask: - setup of mask for message filtering
1221 * @chip: pointer to chip state structure
1222 * @code: can message acceptance code
1223 * @mask: can message acceptance mask
1225 * Return Value: negative value reports error.
1226 * File: src/mcp2515.c
1228 int mcp2515_standard_mask(struct canchip_t *chip, unsigned short code,
1229 unsigned short mask)
1231 CANMSG("mcp2515_standard_mask not implemented\n");
1236 * mcp2515_clear_objects: - clears state of all message object residing in chip
1237 * @chip: pointer to chip state structure
1239 * Return Value: negative value reports error.
1240 * File: src/mcp2515.c
1242 int mcp2515_clear_objects(struct canchip_t *chip)
1244 CANMSG("mcp2515_clear_objects not implemented\n");
1249 * mcp2515_config_irqs: - tunes chip hardware interrupt delivery
1250 * @chip: pointer to chip state structure
1251 * @irqs: requested chip IRQ configuration
1253 * Return Value: negative value reports error.
1254 * File: src/mcp2515.c
1256 int mcp2515_config_irqs(struct canchip_t *chip, short irqs)
1258 CANMSG("mcp2515_config_irqs not implemented\n");
1266 * mcp2515_irq_handler: - interrupt service routine
1267 * @irq: interrupt vector number, this value is system specific
1268 * @chip: pointer to chip state structure
1270 * Interrupt handler is activated when state of CAN controller chip changes,
1271 * there is message to be read or there is more space for new messages or
1272 * error occurs. The receive events results in reading of the message from
1273 * CAN controller chip and distribution of message through attached
1275 * File: src/mcp2515.c
1277 int mcp2515_irq_handler(int irq, struct canchip_t *chip)
1279 //DEBUGMSG("mcp2515_irq_handler\n");
1281 return CANCHIP_IRQ_ACCEPTED;
1282 if (~chip->flags & CHIP_ATTACHED)
1283 return CANCHIP_IRQ_ACCEPTED;
1285 if(can_spi_acquire_bus(chip, 0)){
1286 #ifdef MCP2515_SPI_ASYNC
1287 /* let the SPI subsystem read interrupt status immediately - the response runs in callbacks */
1288 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
1290 /* do work in tasklet if bus is immediately available */
1291 tasklet_hi_schedule(&((MCP2515_PRIV *)(chip->chip_data))->tasklet_handler);
1292 #endif /* MCP2515_SPI_ASYNC */
1294 else /* do work in workqueue */
1295 queue_work(mcp2515_wq,&((MCP2515_PRIV *)(chip->chip_data))->workqueue_handler);
1297 disable_irq(chip->chip_irq);
1298 return CANCHIP_IRQ_HANDLED;
1302 * mcp2515_wakeup_tx: - wakeups TX processing
1303 * @chip: pointer to chip state structure
1304 * @obj: pointer to message object structure
1306 * Function is responsible for initiating message transmition.
1307 * It is responsible for clearing of object TX_REQUEST flag
1309 * Return Value: negative value reports error.
1310 * File: src/mcp2515.c
1312 int mcp2515_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
1314 DEBUGMSG("mcp2515_wakeup_tx\n");
1316 //can_preempt_disable();
1318 can_msgobj_set_fl(obj,TX_PENDING);
1319 can_msgobj_set_fl(obj,TX_REQUEST);
1321 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
1324 can_msgobj_clear_fl(obj,TX_REQUEST);
1326 can_spi_acquire_bus(chip,1);
1327 rq = read_reg(chip, MCP2515_TXB0CTRL) & mcpTXREQ;
1329 obj->tx_retry_cnt=0;
1330 tx_handler(chip, obj);
1333 #ifdef MCP2515_SPI_ASYNC
1334 /* let the SPI subsystem read interrupt status immediately - the response runs in callbacks */
1335 read_async(chip,MCP2515_CANINTF,1,READ_CANINTF);
1337 /* do work in tasklet if bus is immediately available */
1338 tasklet_hi_schedule(&((MCP2515_PRIV *)(chip->chip_data))->tasklet_handler);
1339 #endif /* MCP2515_SPI_ASYNC */
1342 can_spi_release_bus(chip);
1344 can_msgobj_clear_fl(obj,TX_LOCK);
1345 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
1346 DEBUGMSG("TX looping in mcp2515_wakeup_tx\n");
1348 //can_preempt_enable();
1353 int mcp2515_register(struct chipspecops_t *chipspecops)
1355 DEBUGMSG("mcp2515_register\n");
1356 chipspecops->chip_config=mcp2515_chip_config;
1357 chipspecops->baud_rate=mcp2515_baud_rate;
1358 chipspecops->standard_mask=mcp2515_standard_mask;
1359 chipspecops->extended_mask=mcp2515_extended_mask;
1360 chipspecops->message15_mask=mcp2515_extended_mask;
1361 chipspecops->clear_objects=mcp2515_clear_objects;
1362 chipspecops->config_irqs=mcp2515_config_irqs;
1363 chipspecops->pre_read_config=mcp2515_pre_read_config;
1364 chipspecops->pre_write_config=mcp2515_pre_write_config;
1365 chipspecops->send_msg=mcp2515_send_msg;
1366 chipspecops->check_tx_stat=mcp2515_check_tx_stat;
1367 chipspecops->wakeup_tx=mcp2515_wakeup_tx;
1368 chipspecops->remote_request=mcp2515_remote_request;
1369 chipspecops->enable_configuration=mcp2515_enable_configuration;
1370 chipspecops->disable_configuration=mcp2515_disable_configuration;
1371 chipspecops->attach_to_chip=mcp2515_attach_to_chip;
1372 chipspecops->release_chip=mcp2515_release_chip;
1373 chipspecops->set_btregs=mcp2515_set_btregs;
1374 chipspecops->start_chip=mcp2515_start_chip;
1375 chipspecops->stop_chip=mcp2515_stop_chip;
1376 chipspecops->irq_handler=mcp2515_irq_handler;
1377 chipspecops->irq_accept=NULL;
1378 chipspecops->reset_chip=mcp2515_reset_chip;
1379 chipspecops->get_info=mcp2515_get_info;
1384 * mcp2515_fill_chipspecops - fills chip specific operations
1385 * @chip: pointer to chip representation structure
1387 * The function fills chip specific operations for mcp2515 (PeliCAN) chip.
1389 * Return Value: returns negative number in the case of fail
1391 int mcp2515_fill_chipspecops(struct canchip_t *chip)
1393 DEBUGMSG("mcp2515_fill_chipspecops\n");
1394 chip->chip_type="mcp2515";
1395 chip->max_objects=3;
1396 mcp2515_register(chip->chipspecops);