can总线驱动的编写

一.系统硬件结构介绍

       系统中 CAN 总线主要用来完成 S3C2410 开发板和 CAN 总线分析仪的数据传输。在S3C2410 开发平台上,MCP2515 芯片用作 CAN 控制器,MCP2551 芯片用作 CAN 收发器,S3C2410 微处理器用作节点控制器。如下图1所示。

can总线驱动的编写_第1张图片


1.1 S3C2410 的 SPI 接口简介
           SPI( Serial Peripheral Interface) 是一个同步串行外围接口,允许 MCU 与各种外围设备以串行方式进行通信。S3C2410 微处理器包括两路 SPI,每一路分别有两个 8 位转移寄存器,用来发送和接收数据。在 SPI 进行传输时,数据同时发送和接收。如果只想发送数据,接收到的数据将是无效的;如果只想接收数据,应当发送全是 1 的数据。
1.2 MCP2551 功能简介
         MCP2551 是 CAN 协议控制器和物理总线之间的接口。这个器件向总线提供了差动的发送能力,向 CAN 控制器提供了差动的接收能力。
1.3 MCP2515 功能简介
         MCP2515是一款独立CAN控制器,是为简化连接CAN总线的应用而开发的。图2 简要显示了MCP2515的结构框图[3]。该器件主要由三个部分组成:

can总线驱动的编写_第2张图片

(1)CAN 协议引擎(处理所有总线上的报文发送和接收) ;
(2)用来为器件及其运行进行配置的控制逻辑和SRAM寄存器;
(3 )SPI协议模块,用来实现SPI通信模式。
二. 驱动程序设计

驱动源码:

/*
 * Microchip MCP2515 CAN controller driver.
 *
 * Copyright (C) 2007 Embedall Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/workqueue.h>
#include <linux/spi/spi.h>
#include <linux/can/can.h>
#include <linux/delay.h>
#include <linux/can/mcp251x.h>
#include <linux/semaphore.h>
#include <asm/gpio.h>

/* SPI interface instruction set */
#define INSTRUCTION_WRITE       0x02
#define INSTRUCTION_READ        0x03
#define INSTRUCTION_BIT_MODIFY  0x05
#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
#define INSTRUCTION_READ_RXB(n) (0x90 + 4 * (n))
#define INSTRUCTION_RESET       0xc0
#define INSTRUCTION_RTS(n)	(0x80 + (1<<n))
#define INSTRUCTION_RX_STATE    0xb0
#  define RX_STATE_RTR		 0x04
#  define RX_STATE_IDE		 0x08
#define INSTRUCTION_CAN_STATE   0xa0
#  define CAN_STATE_TX2IF	 0x01
#  define CAN_STATE_TX2REQ 	 0x02
#  define CAN_STATE_TX1IF	 0x04
#  define CAN_STATE_TX1REQ       0x08
#  define CAN_STATE_TX0IF        0x10
#  define CAN_STATE_TX0REQ 	 0x20
#  define CAN_STATE_RX1IF	 0x40
#  define CAN_STATE_RX0IF	 0x80

/* MPC251x registers */
#define CANSTAT           0x0e
#define CANCTRL           0x0f
#  define CANCTRL_REQOP_MASK        0xe0
#  define CANCTRL_REQOP_CONF        0x80
#  define CANCTRL_REQOP_LISTEN_ONLY 0x60
#  define CANCTRL_REQOP_LOOPBACK    0x40
#  define CANCTRL_REQOP_SLEEP       0x20
#  define CANCTRL_REQOP_NORMAL      0x00
#  define CANCTRL_OSM               0x08
#  define CANCTRL_ABAT              0x10
#define TEC           0x1c
#define REC           0x1d
#define CNF1          0x2a
#define CNF2          0x29
#  define CNF2_BTLMODE  0x80
#define CNF3          0x28
#  define CNF3_SOF      0x08
#  define CNF3_WAKFIL   0x04
#  define CNF3_PHSEG2_MASK 0x07
#define CANINTE       0x2b
#  define CANINTE_MERRE 0x80
#  define CANINTE_WAKIE 0x40
#  define CANINTE_ERRIE 0x20
#  define CANINTE_TX2IE 0x10
#  define CANINTE_TX1IE 0x08
#  define CANINTE_TX0IE 0x04
#  define CANINTE_RX1IE 0x02
#  define CANINTE_RX0IE 0x01
#define CANINTF       0x2c
#  define CANINTF_MERRF 0x80
#  define CANINTF_WAKIF 0x40
#  define CANINTF_ERRIF 0x20
#  define CANINTF_TX2IF 0x10
#  define CANINTF_TX1IF 0x08
#  define CANINTF_TX0IF 0x04
#  define CANINTF_RX1IF 0x02
#  define CANINTF_RX0IF 0x01
#define EFLG          0x2d
#  define EFLG_RX1OVR   0x80
#  define EFLG_RX0OVR   0x40
#define TXBCTRL(n)  ((n * 0x10) + 0x30)
#  define TXBCTRL_TXREQ  0x08
#  define TXBCTRL_TXPRI(n) (n)
#  define TXBCTRL_TXERR	   (1 << 4)
#  define TXBCTRL_MLOA     (1 << 5)
#  define TXBCTRL_ABTF     (1 << 6)
#define RXBCTRL(n)  ((n * 0x10) + 0x60)
#  define RXBCTRL_MASK   0x60
#  define RXBCTRL_RXRTR  0x08
#  define RXBCTRL_BULK	(1 << 2)
#  define RXBCTRL_RXM_MACH_ALL	(0 << 6)
#  define RXBCTRL_RXM_MACH_STD	(1 << 6)
#  define RXBCTRL_RXM_MACH_EXT	(2 << 6)
#  define RXBCTRL_TXM_MACH_OFF	(3 << 6)
#  define RXBCTRL_FILHIT_MASK    0x07
#define RXM_BASE(n)   (0x20 + (n *  4))
#define RXF_BASE(n)   ((n>2)?(0x10 + (n-3)*4):(0x00 + (n*4)))
	
	

#define SJW1            0x00
#define SJW2            0x40
#define SJW3            0x80
#define SJW4            0xC0

#define BTLMODE_CNF3    0x80

#define SEG1            0x00
#define SEG2            0x01
#define SEG3            0x02
#define SEG4            0x03
#define SEG5            0x04
#define SEG6            0x05
#define SEG7            0x06
#define SEG8            0x07

#define BRP1            0x00
#define BRP2            0x01
#define BRP3            0x02
#define BRP4            0x03
#define BRP5            0x04
#define BRP6            0x05
#define BRP7            0x06
#define BRP8            0x07

//#define CAN_FOSC_12MHZ
#define CAN_FOSC_16MHZ

#if defined(CAN_FOSC_12MHZ)
#define CAN_CNF1_10K		(SJW3 | 0x1d)
#define CAN_CNF2_10K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_10K		(SEG6)

#define CAN_CNF1_20K		(SJW2 | 0x0E)
#define CAN_CNF2_20K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_20K		(SEG6)

#define CAN_CNF1_50K		(SJW1 | 0x05)
#define CAN_CNF2_50K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_50K		(SEG6)

#define CAN_CNF1_100K		(SJW1 | BRP3)
#define CAN_CNF2_100K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_100K		(SEG6)

#define CAN_CNF1_125K		(SJW1 | BRP3)
#define CAN_CNF2_125K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_125K		(SEG4)

#define CAN_CNF1_250K		(SJW1 | BRP2)
#define CAN_CNF2_250K		(BTLMODE_CNF3|(SEG3<<3)|SEG5)
#define CAN_CNF3_250K		(SEG3)

#define CAN_CNF1_500K		(SJW1 | BRP1)
#define CAN_CNF2_500K		(BTLMODE_CNF3|(SEG3<<3)|SEG5)
#define CAN_CNF3_500K		(SEG3)

#define CAN_CNF1_750K		(SJW1 | BRP1)
#define CAN_CNF2_750K		(BTLMODE_CNF3|(SEG3<<2)|SEG1)
#define CAN_CNF3_750K		(SEG3)

#define CAN_CNF1_1000K  	(SJW1 | BRP1)
#define CAN_CNF2_1000K  	(BTLMODE_CNF3|(SEG2<<3)|SEG1)
#define CAN_CNF3_1000K		(SEG2)
#elif defined(CAN_FOSC_16MHZ)
#define CAN_CNF1_10K		(SJW1 | 0x31)
#define CAN_CNF2_10K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_10K		(SEG4)

#define CAN_CNF1_20K		(SJW1 | 0x18)
#define CAN_CNF2_20K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_20K		(SEG4)

#define CAN_CNF1_50K		(SJW1 | 0x09)
#define CAN_CNF2_50K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_50K		(SEG4)

#define CAN_CNF1_100K		(SJW1 | BRP5)
#define CAN_CNF2_100K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_100K		(SEG4)

#define CAN_CNF1_125K		(SJW1 | BRP4)
#define CAN_CNF2_125K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_125K		(SEG4)

#define CAN_CNF1_250K		(SJW1 | BRP2)
#define CAN_CNF2_250K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_250K		(SEG4)

#define CAN_CNF1_500K		(SJW1 | BRP1)
#define CAN_CNF2_500K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_500K		(SEG4)

#define CAN_CNF1_750K		(SJW1 | BRP1)
#define CAN_CNF2_750K		(BTLMODE_CNF3|(SEG3<<3)|SEG4)
#define CAN_CNF3_750K		(SEG3)

#define CAN_CNF1_800K		(SJW1 | BRP1)
#define CAN_CNF2_800K		(BTLMODE_CNF3|(SEG3<<3)|SEG3)
#define CAN_CNF3_800K		(SEG3)

#define CAN_CNF1_1000K  	(SJW1 | BRP1)
#define CAN_CNF2_1000K  	(BTLMODE_CNF3|(SEG2<<3)|SEG3)
#define CAN_CNF3_1000K		(SEG2)
#endif	/* end define CAN_FOSC_12MHZ */

/* Buffer size required for the largest SPI transfer (i.e., reading a frame).
 */
#define SPI_TRANSFER_BUF_LEN (2*(6 + CAN_FRAME_MAX_DATA_LEN))

/* Buffer size required for ring buffer of receive and send */
#define MCP251X_BUF_LEN 8



#define CAN_DEV_MAX 8

#define DRIVER_NAME "mcp2515"

static dev_t can_devt;

static int can_minor = 0;

static struct class *can_class;

static int write_udelay=1024;

struct mcp251x {
	struct cdev cdev;
	//struct class_device *class_dev;
	struct device *class_dev;
	struct semaphore lock;	 /* semaphore for spi bus share. */
	struct semaphore rxblock;	 /* semaphore for ring buffer of receive. */
	struct semaphore txblock;	 /* semaphore for ring buffer of send. */
	
	uint8_t *spi_transfer_buf;	 /* temp buffer for spi bus transfer. */

	struct can_frame rxb[MCP251X_BUF_LEN]; /* ring buffer for receive. */
	struct can_frame txb[MCP251X_BUF_LEN]; /* ring buffer for send. */
	
	int txbin;			 /* pos of in for ring buffer of send. */
	int txbout;			 /* pos of out for ring buffer of send. */
	int rxbin;			 /* pos of in for ring buffer of receive. */
	int rxbout;			 /* pos of out for ring buffer of receive. */
	
	int bit_rate;		 /* save bit rate of current set. */
	int count;			 /* count of the device opened. */
    
	wait_queue_head_t wq;	 /* queue for read process. */
    
	struct work_struct irq_work; /* bottom half of interrupt task. */
    
	struct spi_device *spi;	 /* save the point of struce spi_device. */
	struct can_filter filter;	 /* save the filter data of current set. */
};

/* ........................................................................ */

#if 0
static void mcp251x_start_tx(struct spi_device *spi, uint8_t buf_idx)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	uint8_t *tx_buf;
	int ret;
	
	tx_buf = chip->spi_transfer_buf;
	
	down(&chip->lock);
	
	tx_buf[0] = INSTRUCTION_RTS(buf_idx);
	ret = spi_write(spi, chip->spi_transfer_buf, 1);
	if (ret < 0)
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);

	up(&chip->lock);
}
#endif

static uint8_t mcp251x_read_state(struct spi_device *spi, uint8_t cmd)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	uint8_t *tx_buf, *rx_buf;
	uint8_t val;
	int ret;

	tx_buf = chip->spi_transfer_buf;
	rx_buf = chip->spi_transfer_buf + 8;

	down(&chip->lock);
	
	tx_buf[0] = cmd;
	ret = spi_write_then_read(spi, tx_buf, 1, rx_buf, 1);
	if (ret < 0) {
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);
		val = 0;
	} else
		val = rx_buf[0];

	up(&chip->lock);

	return val;
}


static uint8_t mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	uint8_t *tx_buf, *rx_buf;
	uint8_t val;
	int ret;

	tx_buf = chip->spi_transfer_buf;
	rx_buf = chip->spi_transfer_buf + 8;

	down(&chip->lock);
	
	tx_buf[0] = INSTRUCTION_READ;
	tx_buf[1] = reg;
	ret = spi_write_then_read(spi, tx_buf, 2, rx_buf, 1);
	if (ret < 0) {
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);
		val = 0;
	} else
		val = rx_buf[0];

	up(&chip->lock);

	return val;
}


static void mcp251x_write_reg(struct spi_device *spi, uint8_t reg, uint8_t val)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	int ret;

	down(&chip->lock);

	chip->spi_transfer_buf[0] = INSTRUCTION_WRITE;
	chip->spi_transfer_buf[1] = reg;
	chip->spi_transfer_buf[2] = val;

	ret = spi_write(spi, chip->spi_transfer_buf, 3);
	if (ret < 0)
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);

	up(&chip->lock);
}


static void mcp251x_write_bits(struct spi_device *spi, uint8_t reg, uint8_t mask, uint8_t val)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	int ret;

	down(&chip->lock);

	chip->spi_transfer_buf[0] = INSTRUCTION_BIT_MODIFY;
	chip->spi_transfer_buf[1] = reg;
	chip->spi_transfer_buf[2] = mask;
	chip->spi_transfer_buf[3] = val;

	ret = spi_write(spi, chip->spi_transfer_buf, 4);
	if (ret < 0)
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);

	up(&chip->lock);
}

static void mcp251x_hw_reset(struct spi_device *spi)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	int ret;

	down(&chip->lock);

	chip->spi_transfer_buf[0] = INSTRUCTION_RESET;

	ret = spi_write(spi, chip->spi_transfer_buf, 1);
	if (ret < 0)
		dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);
	
	up(&chip->lock);
}


static void __devinit mcp251x_hw_init(struct spi_device *spi)
{
	mcp251x_hw_reset(spi);	
	mcp251x_write_reg(spi,0x0c,0x0c);
}

static void mcp251x_hw_sleep(struct spi_device *spi)
{
#if 0   /* sleep disable */
	mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
#endif
}

static void mcp251x_hw_wakeup(struct spi_device *spi)
{
	/* Can only wake up by generating a wake-up interrupt. */
	mcp251x_write_bits(spi, CANINTE, CANINTE_WAKIE, CANINTE_WAKIE);
	mcp251x_write_bits(spi, CANINTF, CANINTF_WAKIF, CANINTF_WAKIF);
	mdelay(10);
}


static int mcp251x_set_bit_rate(struct spi_device *spi, int bit_rate)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	unsigned char canctrl,val;
#if 0
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
	int tqs; /* tbit/TQ */
	int brp;
	int ps1, ps2, propseg, sjw;

	/* Determine the BRP value that gives the requested bit rate. */
	for(brp = 0; brp < 8; brp++) {
		tqs = pdata->f_osc / (2 * (brp + 1)) / bit_rate;
		if (tqs >= 5 && tqs <= 25
		    && (pdata->f_osc / (2 * (brp + 1)) / tqs) == bit_rate)
			break;
	}
	if (brp >= 8)
		return -EINVAL;

	/* The CAN bus bit time (tbit) is determined by:
	 *   tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ
	 * with:
	 *     SyncSeg = 1
	 *     sample point (between PS1 and PS2) must be at 60%-70% of the bit time
	 *     PropSeg + PS1 >= PS2
	 *     PropSeg + PS1 >= Tdelay
	 *     PS2 > SJW
	 *     1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8
	 * SJW = 1 is sufficient in most cases.
	 * Tdelay is usually 1 or 2 TQ.
	 */

	propseg = ps1 = ps2 = (tqs - 1) / 3;
	if (tqs - (1 + propseg + ps1 + ps2) == 2)
		ps1++;
	if (tqs - (1 + propseg + ps1 + ps2) == 1)
		ps2++;
	sjw = 1;
	
	printk("bit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n",
		brp, tqs, propseg, ps1, ps2, sjw);

	dev_dbg(&spi->dev,"bit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n",
		brp, tqs, propseg, ps1, ps2, sjw);

	mcp251x_write_reg(spi, CNF1, ((sjw-1) << 6) | brp);
	mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1));
	mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, (ps2-1));
	chip->bit_rate = pdata->f_osc / (2 * (brp + 1)) / tqs;
#endif
#if 1
	canctrl = mcp251x_read_reg(spi, CANCTRL);
/*	if(canctrl == 0) {
		printk("mcp2515 read CANCTRL reg error!\n");
		return -1;
	} else {
		printk("mcp2515 read CANCTRL reg [%x] ok!\n", canctrl);
	}*/
	do {
		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_CONF);
		val = mcp251x_read_reg(spi, CANCTRL);
	}while((val&0xe0) != CANCTRL_REQOP_CONF);
			
	switch(bit_rate) {
		case 10000:
			/* save the state and put it to config mode. */
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_10K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_10K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_10K);
			write_udelay=12800;
		break;
		
		case 20000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_20K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_20K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_20K);
			write_udelay=6400;
		break;
		
		case 50000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_50K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_50K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_50K);
			write_udelay=2560;
		break;
		
		case 100000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_100K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_100K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_100K);
			write_udelay=1280;
		break;
		
		case 125000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_125K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_125K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_125K);
			write_udelay=1024;
		break;
		
		case 250000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_250K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_250K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_250K);
			write_udelay=512;
		break;

		case 500000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_500K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_500K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_500K);
			write_udelay=256;
		break;
		
		case 750000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_750K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_750K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_750K);
			write_udelay=171;
		break;

		case 800000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_800K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_800K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_800K);
			write_udelay=160;
		break;

		case 1000000:
			mcp251x_write_reg(spi, CNF1, CAN_CNF1_1000K);
			mcp251x_write_reg(spi, CNF2, CAN_CNF2_1000K);
			mcp251x_write_reg(spi, CNF3, CAN_CNF3_1000K);
			write_udelay=128;
		break;

		default:
			printk("<kernel>: baud rate %d not support\n", bit_rate);
		break;
	}	
	mcp251x_write_reg(spi, CANCTRL, canctrl);
	chip->bit_rate = bit_rate;
#endif
	
	return 0;
}

static int mcp251x_get_bit_rate(struct spi_device *spi)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);

	return chip->bit_rate;
}

static int mcp251x_set_filter(struct spi_device *spi, struct can_filter *filter)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	
	uint8_t canctrl;
	uint8_t local_buf;
	int i;
	
	canctrl = mcp251x_read_reg(spi, CANCTRL);
	
	mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_CONF);

	for (i=0; i<CAN_FILTER_REG_NUM; i++) {
		if (filter->fid[i].active == 0) {
			local_buf = 0;
			mcp251x_write_reg(spi, RXF_BASE(i)+0, local_buf);
#if 1	
			/* set RXFnSIDL  EXIDE(bit 3) = 0 for receive standard frame */
			mcp251x_write_reg(spi, RXF_BASE(i)+1, local_buf);
#else		/* set RXFnSIDL  EXIDE(bit 3) = 1 for receive extend frame */		
			mcp251x_write_reg(spi, RXF_BASE(i)+1, local_buf | 0x08);
#endif			
			mcp251x_write_reg(spi, RXF_BASE(i)+2, local_buf);
			mcp251x_write_reg(spi, RXF_BASE(i)+3, local_buf);
			continue;
		}
		local_buf = filter->fid[i].id >> 3;
		mcp251x_write_reg(spi, RXF_BASE(i)+0, local_buf);
		local_buf = (filter->fid[i].id << 5) | (filter->fid[i].ide << 3) | (filter->fid[i].eid >> 16);
#if 1		
		mcp251x_write_reg(spi, RXF_BASE(i)+1, local_buf);	
#else		
		mcp251x_write_reg(spi, RXF_BASE(i)+1, local_buf | 0x08);	
#endif		
		local_buf = filter->fid[i].eid >> 8;
		mcp251x_write_reg(spi, RXF_BASE(i)+2, local_buf);
		local_buf = filter->fid[i].eid;
		mcp251x_write_reg(spi, RXF_BASE(i)+3, local_buf);
	}
	for (i=0; i<2; i++) {
		local_buf = filter->sidmask >> 3;
		mcp251x_write_reg(spi, RXM_BASE(i)+0, local_buf);
		local_buf = (filter->sidmask << 5) | (filter->eidmask >> 16);
		mcp251x_write_reg(spi, RXM_BASE(i)+1, local_buf);
		local_buf = filter->eidmask >> 8;
		mcp251x_write_reg(spi, RXM_BASE(i)+2, local_buf);
		local_buf = filter->eidmask;
		mcp251x_write_reg(spi, RXM_BASE(i)+3, local_buf);
	}
	
	mcp251x_write_reg(spi, CANCTRL, canctrl);
	
    /* set receive buffer work mode */		
	mcp251x_write_bits(spi, RXBCTRL(0), RXBCTRL_MASK, filter->mode << 5);
	mcp251x_write_bits(spi, RXBCTRL(1), RXBCTRL_MASK, filter->mode << 5);
	
	memcpy(&chip->filter, filter, sizeof(struct can_filter));
	
	return 0;
}

static int mcp251x_get_filter(struct spi_device *spi, struct can_filter *filter)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);

	memcpy(filter, &chip->filter, sizeof(struct can_filter));
		
	return 0;	
}

/* If MCP251X ready, copy data from ring buffer to MCP251X send buffer and set
 * TXBCTRL_TXREQ.
 */
static int mcp251x_hw_tx(struct spi_device *spi, int tx_buf_idx)
{

	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	uint8_t buf[13] ;
//	unsigned char val;
	struct can_frame *frame;
//	int ret;
	int i;
	

	dev_dbg(&spi->dev,"%s()\n", __FUNCTION__);

	if (chip->txbout != chip->txbin) {

		if (down_interruptible(&chip->txblock))
			return -ERESTARTSYS;
		
		frame = &chip->txb[chip->txbout];
			
	//	down(&chip->lock);
			
		if (frame->header.dlc > CAN_FRAME_MAX_DATA_LEN)
			frame->header.dlc = CAN_FRAME_MAX_DATA_LEN;
		if (frame->header.ide == 0)
			frame->header.eid = 0;
	/*		
		buf[0] = INSTRUCTION_LOAD_TXB(tx_buf_idx);
		buf[1] = frame->header.id >> 3;
		buf[2] = (frame->header.id << 5) | (frame->header.ide << 3)
			| (frame->header.eid >> 16);
		buf[3]  = frame->header.eid >> 8;
		buf[4]  = frame->header.eid;
		buf[5] = (frame->header.rtr << 6) | frame->header.dlc;
		memcpy(buf + 6, frame->data, frame->header.dlc);
	
		for(i=0;i<frame->header.dlc+6;i++) {
			printk("buf[%d] : %d\n",i,buf[i]);		
		}
		ret = spi_write(spi, buf, 6 + CAN_FRAME_MAX_DATA_LEN);
		if (ret < 0) 
			dev_dbg(&spi->dev,"%s: failed: ret = %d\n", __FUNCTION__, ret);
	*/
		
		buf[0] = frame->header.id >> 3;
		buf[1] = (frame->header.id << 5) | (frame->header.ide << 3)	| (frame->header.eid >> 16);
		buf[2]  = frame->header.eid >> 8;
		buf[3]  = frame->header.eid;
		buf[4] = (frame->header.rtr << 6) | frame->header.dlc;
		memcpy(buf + 5, frame->data, frame->header.dlc);
		/*		
		for(i=0;i<frame->header.dlc+5;i++) {
			printk("buf[%d] : %x\n",i,buf[i]);		
		}
		*/
		if (tx_buf_idx == 0) {
			for(i=0;i<(frame->header.dlc+5);i++) {
				mcp251x_write_reg(spi,(0x31+i),buf[i]);
			}
		} else if(tx_buf_idx ==1) {
			for(i=0;i<(frame->header.dlc+5);i++)  {
				mcp251x_write_reg(spi,(0x41+i),buf[i]);
			}
		} else {
			for(i=0;i<(frame->header.dlc+5);i++)  {
				mcp251x_write_reg(spi,(0x51+i),buf[i]);
			}
		}

	//	up(&chip->lock);
		
		/* update pos of ring buffer */
		chip->txbout++;
		if (chip->txbout >= MCP251X_BUF_LEN)
			chip->txbout = 0;

		up(&chip->txblock);
		mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
	}
	return 0;
}

/* Receive data from internat buffer of MCP251X and save it to ring buffer.
 */
static int mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	uint8_t rx_buf[13];
//	int ret;
	struct can_frame *frame;
	int i;
	
	if (down_interruptible(&chip->rxblock))
		return -ERESTARTSYS;
		
	frame = &chip->rxb[chip->rxbin];

//	down(&chip->lock);
	/*
	buf[0] = INSTRUCTION_READ_RXB(buf_idx);
	rx_buf = buf + (6 + CAN_FRAME_MAX_DATA_LEN);
	ret = spi_write_then_read(spi, buf, 1, rx_buf, 13);
	if (ret < 0)
		dev_dbg(&spi->dev, "%s: failed: ret = %d\n", __FUNCTION__, ret);
	*/
	if (buf_idx == 0) 
		for(i=0;i<(5 + CAN_FRAME_MAX_DATA_LEN);i++) {
			rx_buf[i] = mcp251x_read_reg(spi,0x61+i);	
		}
	else
		for(i=0;i<(5 + CAN_FRAME_MAX_DATA_LEN);i++) {
			rx_buf[i] = mcp251x_read_reg(spi,0x71+i);	
		}

	frame->header.id = (rx_buf[0] << 3) | (rx_buf[1] >> 5);
	frame->header.ide = (rx_buf[1] >> 3) & 0x1;
	frame->header.srr = (rx_buf[1] >> 4) & 0x1;
	if (frame->header.ide == 1)
		frame->header.eid = (rx_buf[1] << 16) | (rx_buf[2] << 8) | rx_buf[3];
	else
		frame->header.eid = 0;
	frame->header.rtr = (rx_buf[4] >> 6) & 0x1;
	frame->header.rb1 = (rx_buf[4] >> 5) & 0x1;
	frame->header.rb0 = (rx_buf[4] >> 4) & 0x1;
	frame->header.dlc = rx_buf[4] & 0x0f;
	memcpy(frame->data, rx_buf + 5, CAN_FRAME_MAX_DATA_LEN);
	
//	up(&chip->lock);

	/* update pos of ring buffer */
	chip->rxbin++;
	if (chip->rxbin >= MCP251X_BUF_LEN)
		chip->rxbin = 0;
			
	up(&chip->rxblock);

	return 0;
}

/* ........................................................................ */

/* bottom half task for interrupt */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
static void mcp251x_irq_handler(struct work_struct *work)
{
	struct mcp251x *chip = container_of(work, struct mcp251x, irq_work);
	struct spi_device *spi = chip->spi;
#else
static void mcp251x_irq_handler(void *dev_id)
{
	struct spi_device *spi = dev_id;
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
#endif
	uint8_t intf, rxs;

	for(;;) {
		
		intf = mcp251x_read_reg(spi, CANINTF);
		if (intf == 0x00)
			break;

		dev_dbg(&spi->dev,"interrupt:%s%s%s%s%s%s%s%s\n",
			(intf & CANINTF_MERRF) ? " MERR":"",
			(intf & CANINTF_WAKIF) ? " WAK":"",
			(intf & CANINTF_ERRIF) ? " ERR":"",
			(intf & CANINTF_TX2IF) ? " TX2":"",
			(intf & CANINTF_TX1IF) ? " TX1":"",
			(intf & CANINTF_TX0IF) ? " TX0":"",
			(intf & CANINTF_RX1IF) ? " RX1":"",
			(intf & CANINTF_RX0IF) ? " RX0":"");
			
		rxs = mcp251x_read_state(spi, INSTRUCTION_RX_STATE); 
		dev_dbg(&spi->dev, 
			"rx_state:%s%s\n",
			(rxs & RX_STATE_IDE) ? " IDE":"",
			(rxs & RX_STATE_RTR) ? " RTR":"");
			
		if (intf & CANINTF_MERRF) {
#if 0
			uint8_t txbnctrl;
			/* if there are no pending Tx buffers, restart queue */
			txbnctrl = mcp251x_read_reg(spi, TXBCTRL(0));
			if (!(txbnctrl & TXBCTRL_TXREQ))
				netif_wake_queue(&chip->can->ndev);
#endif
		}
		if (intf & CANINTF_ERRIF) {
			uint8_t eflg = mcp251x_read_reg(spi, EFLG);
	    
			dev_dbg(&spi->dev, "EFLG = 0x%02x\n", eflg);
	    
			if (eflg & (EFLG_RX0OVR | EFLG_RX1OVR)) {
#if 0
				if (eflg & EFLG_RX0OVR)
					chip->stats.rx_over_errors++;
				if (eflg & EFLG_RX1OVR)
					chip->stats.rx_over_errors++;
#endif
				mcp251x_write_reg(spi, EFLG, 0x00);
			}
		}

		if (intf & CANINTF_TX0IF) /* If ready to send, copy data to send buffer. */
			mcp251x_hw_tx(spi, 0);
		if (intf & CANINTF_TX1IF)
			mcp251x_hw_tx(spi, 1);
		if (intf & CANINTF_TX2IF)
			mcp251x_hw_tx(spi, 2);
		if (intf & CANINTF_RX0IF) /* If received data, copy data to ring buffer. */
			mcp251x_hw_rx(spi, 0);
		if (intf & CANINTF_RX1IF)
			mcp251x_hw_rx(spi, 1);
	
		mcp251x_write_bits(spi, CANINTF, intf, 0x00);
	
		/* If ring buffer of receive is not empty, wake up the read queue. */
		if (chip->rxbin != chip->rxbout)
			wake_up_interruptible(&chip->wq);
	}
}


static irqreturn_t mcp251x_irq(int irq, void *dev_id)
{
	struct spi_device *spi = dev_id;
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);

	/* Can't do anything in interrupt context so fire of the interrupt
	 * handling workqueue. */
	schedule_work(&chip->irq_work);

	return IRQ_HANDLED;
}

/* ........................................................................ */

static int mcp251x_open(struct inode *inode, struct file *file)
{
	struct mcp251x *chip = container_of(inode->i_cdev, struct mcp251x, cdev);
	struct spi_device *spi = chip->spi;
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
	
	file->private_data = chip;

	if (!chip->count) {
		
		if (pdata->transceiver_enable)
			pdata->transceiver_enable(1);

		mcp251x_hw_reset(spi);
		mcp251x_hw_wakeup(spi);

		/* Enable interrupts */
		mcp251x_write_reg(spi, CANINTE,
				  CANINTE_ERRIE | CANINTE_TX2IE
				  | CANINTE_TX1IE | CANINTE_TX0IE
				  | CANINTE_RX1IE | CANINTE_RX0IE);

		/* put device into normal mode */
		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
		mcp251x_write_reg(spi, RXBCTRL(0), RXBCTRL_BULK);
	}
	
	chip->count++;
	
	return 0;
}

static int mcp251x_release(struct inode *inode, struct file *file)
{
	
	struct mcp251x *chip = container_of(inode->i_cdev, struct mcp251x, cdev);
	struct spi_device *spi = chip->spi;
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;

	chip->count--;
	
	if (chip->count)
		return 0;

	/* disable and clear pending interrupts */
	mcp251x_write_reg(spi, CANINTE, 0x00);
	mcp251x_write_reg(spi, CANINTF, 0x00);

	/* go to sleep */
	mcp251x_hw_sleep(spi);

	if (pdata->transceiver_enable)
		pdata->transceiver_enable(0);
		

	return 0;
}

static int mcp251x_write(struct file *file, const char __user *buf, size_t count, loff_t *ofs)
{
	
	struct mcp251x *chip = file->private_data;
	struct spi_device *spi = chip->spi;
	struct can_frame *frame;
	int ret;
	uint8_t txreq;

	if (count < sizeof(struct can_frame))
		return -EINVAL;

	if (down_interruptible(&chip->txblock))
		return -ERESTARTSYS;
	
	frame = &chip->txb[chip->txbin];
	ret = copy_from_user(frame, buf, sizeof(struct can_frame));
	
	chip->txbin++;
	if (chip->txbin >= MCP251X_BUF_LEN)
		chip->txbin = 0;
	
	up(&chip->txblock);
	
	txreq = mcp251x_read_state(spi, INSTRUCTION_CAN_STATE);
	if (!(txreq & CAN_STATE_TX0REQ)) 
		mcp251x_hw_tx(spi, 0);		
	if (!(txreq & CAN_STATE_TX1REQ)) 
		mcp251x_hw_tx(spi, 1);
	if (!(txreq & CAN_STATE_TX2REQ))
		mcp251x_hw_tx(spi, 2);
	
	udelay(write_udelay);

	return count;
}

static ssize_t mcp251x_read(struct file *file, char __user *buf, size_t count, loff_t *ofs)
{
	
	struct mcp251x *chip = file->private_data;
	struct can_frame *frame;
	
	if (count != sizeof(struct can_frame))
		return -EINVAL;
		
	if (down_interruptible(&chip->rxblock))
		return -ERESTARTSYS;
	
	while (chip->rxbin == chip->rxbout) {
		up(&chip->rxblock);
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;
		if (wait_event_interruptible(chip->wq, (chip->rxbin != chip->rxbout)))
			return -ERESTARTSYS;
		if (down_interruptible(&chip->rxblock))
			return -ERESTARTSYS;
	}
	
	frame = &chip->rxb[chip->rxbout];
	if (copy_to_user(buf, frame, sizeof(struct can_frame))) {
		up(&chip->rxblock);
		return -EFAULT;
	}
	chip->rxbout++;
	if(chip->rxbout >= MCP251X_BUF_LEN)
		chip->rxbout = 0;
		
	up(&chip->rxblock);
		
	return count;
    
#if 0
retry:
	if (chip->rxbin != chip->rxbout) {
		
		down(&chip->rxblock);
		
		frame = &chip->rxb[chip->rxbout];
		if (copy_to_user(buf, frame, sizeof(struct can_frame))) {
			up(&chip->rxblock);
			return -EFAULT;
		}
		chip->rxbout++;
		if(chip->rxbout >= MCP251X_BUF_LEN)
			chip->rxbout = 0;
		
		up(&chip->rxblock);
		
		return count;
	}
	else {
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;
		interruptible_sleep_on(&chip->wq);
		if (signal_pending(current))
			return -ERESTARTSYS;
			
		goto retry;
	}
#endif
}

static int mcp251x_ioctl(struct inode *inode, struct file *file, 
			 unsigned int cmd, unsigned long arg)
{

	struct mcp251x *chip = container_of(inode->i_cdev, struct mcp251x, cdev);
	struct spi_device *spi = chip->spi;
	int ret = 0;

	switch(cmd) {
	
	case CAN_IOCTRESET:		/* reset devcie */
		mcp251x_hw_reset(spi);
		break;
	case CAN_IOCTWAKEUP:	/* wake up device */
		mcp251x_hw_wakeup(spi);
		break;
	case CAN_IOCSRATE:		/* set bit rate */
		ret = mcp251x_set_bit_rate(spi, (int)arg);
		mdelay(10);
		break;
	case CAN_IOCGRATE:		/* get bit rate */
		*((int *)arg) = mcp251x_get_bit_rate(spi);
		break;
	case CAN_IOCSFILTER:	/* set filter */
		ret = mcp251x_set_filter(spi, (struct can_filter *)arg);
		break;
	case CAN_IOCGFILTER:	/* get filter */
		ret = mcp251x_get_filter(spi, (struct can_filter *)arg);
		break;
	case CAN_IOCTNORMALMODE:	/* turn to normal mode */
		//mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_NORMAL);
		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
		break;
	case CAN_IOCTLOOPBACKMODE:	/* turn to loopback mode */
		//mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_LOOPBACK);
		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
		break;
	case CAN_IOCTLISTENONLYMODE: /* turn to listen only mode */
		//mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_LISTEN_ONLY);
		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);
		break;
	case CAN_IOCTSLEEPMODE:	/* turn to sleep mode */
		mcp251x_hw_sleep(spi);
		break;
	default:
		return -ENOTTY;
	}
	
	return ret;
}

static const struct file_operations mcp251x_fops = {
	.owner = THIS_MODULE,
	.read = mcp251x_read,
	.write = mcp251x_write,
	.ioctl = mcp251x_ioctl,
	.open = mcp251x_open,
	.release = mcp251x_release,
};

/* ........................................................................ */

static int __devexit mcp251x_remove(struct spi_device *spi)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);

	dev_dbg(&spi->dev, "%s: stop\n",  __FUNCTION__);

	device_unregister(chip->class_dev);

	cdev_del(&chip->cdev);
	free_irq(spi->irq, spi);
	kfree(chip->spi_transfer_buf);

	return 0;
}

static int __devinit mcp251x_probe(struct spi_device *spi)
{
	struct mcp251x *chip;
	int ret = 0;
	int irq;

	dev_dbg(&spi->dev,"%s: start\n",  __FUNCTION__);

	chip = kmalloc(sizeof(struct mcp251x), GFP_KERNEL);
	if (!chip) {
		ret = -ENOMEM;
		goto error_alloc;
	}

	dev_set_drvdata(&spi->dev, chip);
	
	chip->txbin = chip->txbout = 0;
	chip->rxbin = chip->rxbout = 0;
	chip->count = 0;
	chip->spi = spi;
	init_MUTEX(&chip->lock);
	init_MUTEX(&chip->txblock);
	init_MUTEX(&chip->rxblock);
	init_waitqueue_head(&chip->wq);
    
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
	INIT_WORK(&chip->irq_work, mcp251x_irq_handler);
#else
	INIT_WORK(&chip->irq_work, mcp251x_irq_handler, spi);
#endif
    
	chip->spi_transfer_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
	if (!chip->spi_transfer_buf) {
		ret = -ENOMEM;
		goto error_buf;
	}
	
	ret = gpio_request(spi->irq, spi->modalias);
	if (ret < 0) {
		pr_err("mcp251x: failed to request GPIO %d,"
						" error %d\n", spi->irq, ret);
		goto error_irq;
	}

	ret = gpio_direction_input(spi->irq);
	if (ret < 0) {
		pr_err("mcp251x: failed to configure input"
						" direction for GPIO %d, error %d\n",
						spi->irq, ret);
		gpio_free(spi->irq);
		goto error_irq;
	}

	irq = gpio_to_irq(spi->irq);
	if (irq < 0) {
		ret = irq;
		pr_err("mcp251x: Unable to get irq number"
						" for GPIO %d, error %d\n",
						spi->irq, ret);
		gpio_free(spi->irq);
		goto error_irq;
	}

	ret = request_irq(irq, mcp251x_irq,IRQF_SAMPLE_RANDOM, DRIVER_NAME, spi);// SA_SAMPLE_RANDOM,
	if (ret < 0) {
		dev_err(&spi->dev,"request irq %d failed (ret = %d)\n", spi->irq, ret);
		gpio_free(spi->irq);
		goto error_irq;
	}
	
	cdev_init(&chip->cdev, &mcp251x_fops);
	chip->cdev.owner = THIS_MODULE;
	ret = cdev_add(&chip->cdev, MKDEV(MAJOR(can_devt), can_minor), 1);
	if (ret < 0) {
		dev_err(&spi->dev, "register char device failed (ret = %d)\n", ret);
		goto error_register;
	}

	chip->class_dev = device_create(can_class, NULL,
					      MKDEV(MAJOR(can_devt), can_minor),
					      &spi->dev, "can%d", can_minor);
	if (IS_ERR(chip->class_dev)) {
		dev_err(&spi->dev, "cannot create CAN class device\n");
		ret = PTR_ERR(chip->class_dev);
		goto error_class_reg;
	}
	
	dev_info(&spi->dev, "device register at dev(%d:%d)\n",
		 MAJOR(can_devt), can_minor);
	
	mcp251x_hw_init(spi);
	ret = mcp251x_set_bit_rate(spi, 125000); /* A reasonable default */
	if(ret == -1) {
		printk("mcp2515 set bit rate error!\n");
		cdev_del(&chip->cdev);
		free_irq(spi->irq, spi);
		kfree(chip->spi_transfer_buf);
		kfree(chip);
		return ret;
	}
	mcp251x_hw_sleep(spi);

	can_minor++;
	
	return 0;
	
error_class_reg:
	cdev_del(&chip->cdev);
error_register:
	free_irq(spi->irq, spi);
error_irq:
	free_irq(gpio_to_irq(spi->irq), spi);
	gpio_free(spi->irq);
	kfree(chip->spi_transfer_buf);
error_buf:
	kfree(chip);
error_alloc:
	return ret;
}

#ifdef CONFIG_PM
static int mcp251x_suspend(struct spi_device *spi, pm_message_t mesg)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;

	if (chip->count)
		return 0;

	mcp251x_hw_sleep(spi);
	if (pdata->transceiver_enable)
		pdata->transceiver_enable(0);

	return 0;
}

static int mcp251x_resume(struct spi_device *spi)
{
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;

	if (!chip->count)
		return 0;
		
	if (pdata->transceiver_enable)
		pdata->transceiver_enable(1);
	mcp251x_hw_wakeup(spi);

	return 0;
}
#endif

static struct spi_driver mcp251x_driver = {
	.driver = {
		.name	= DRIVER_NAME,
		.bus	= &spi_bus_type,
		.owner	= THIS_MODULE,
	},
	.probe	= mcp251x_probe,
	.remove	= __devexit_p(mcp251x_remove),
#ifdef CONFIG_PM
	.suspend	= mcp251x_suspend,
	.resume	= mcp251x_resume,
#endif
};

static int __init mcp251x_init(void)
{
	int ret;
	
	can_class = class_create(THIS_MODULE, "can");
	if (IS_ERR(can_class))
		return PTR_ERR(can_class);
	ret = alloc_chrdev_region(&can_devt, 0, CAN_DEV_MAX, DRIVER_NAME);
	if (ret < 0) {
		printk(KERN_ERR "%s: failed to allocate char dev region\n",
		       __FILE__);
		class_destroy(can_class);
		return ret;
	}
	return spi_register_driver(&mcp251x_driver);
}
module_init(mcp251x_init);

static void __exit mcp251x_exit(void)
{
	class_destroy(can_class);
	unregister_chrdev_region(can_devt, CAN_DEV_MAX);
	spi_unregister_driver(&mcp251x_driver);
}
module_exit(mcp251x_exit);


MODULE_DESCRIPTION("MCP251x CAN controller driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Quanlin.Bai");




你可能感兴趣的:(can总线驱动的编写)