can总线驱动源码分析

/*
 * 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,
};

/* 
 *CAN驱动移除函数 
 *probe() 和remove() 函数应该使用__devinit 和__devexit 标记,且只能标记probe() 和remove()
 */
static int __devexit mcp251x_remove(struct spi_device *spi)
{
	/*
	 *dev_get_drvdata返回驱动数据的指针,参数设备指针
	 */
	struct mcp251x *chip = dev_get_drvdata(&spi->dev);

	/*内核使用dev_dbg来控制输出信息,这个函数的实质是调用 printk(KERN_DEBUG )来输出打印信息*/
	dev_dbg(&spi->dev, "%s: stop\n",  __FUNCTION__);

	/*
	 *在device_unregister 函数中,驱动核心将删除这个设备的驱动程序(如果有)指向
	 *这个设备的符号链接, 并从它的内部设备链表中删除该设备
	 */
	device_unregister(chip->class_dev);
	
	/*删除一个设备*/
	cdev_del(&chip->cdev);

	/*释放中断*/
	free_irq(spi->irq, spi);

	/*kfree负责回收使用的内存*/
	kfree(chip->spi_transfer_buf);

	return 0;
}
/
/* 
 *CAN驱动探测函数 
 *probe() 和remove() 函数应该使用__devinit 和__devexit 标记,且只能标记probe() 和remove()
 */
static int __devinit mcp251x_probe(struct spi_device *spi)
{
	struct mcp251x *chip;
	int ret = 0;
	int irq;

	/*内核使用dev_dbg来控制输出信息 */
	dev_dbg(&spi->dev,"%s: start\n",  __FUNCTION__);

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

	/*
	 static inline void dev_set_drvdata(struct device *dev, void *data)
	 {       
        	dev->driver_data = data;
	 }  
	*/
	dev_set_drvdata(&spi->dev, chip);
	
	chip->txbin = chip->txbout = 0;
	chip->rxbin = chip->rxbout = 0;
	chip->count = 0;
	chip->spi = spi;

	/*
	 * 2.6.25及以后的linux内核版本废除了init_MUTEX函数 .使用 init_MUTEX(sem)的地方统统替换为sema_init(sem, 1); 
	 * Init_MUTEX()函数初始化信号量为互斥量.互斥量为信号量的特例,它可以防止数据被两个不同系统调用读写。
	 */
	init_MUTEX(&chip->lock);
	init_MUTEX(&chip->txblock);
	init_MUTEX(&chip->rxblock);

	/*init_waitqueue_head()函数会将自旋锁初始化为未锁,等待队列初始化为空的双向循环链表*/
	init_waitqueue_head(&chip->wq);
    
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
	/*
	 *#define INIT_WORK(_work, _func, _data),可以理解为
	 *INIT_WORK会在你定义的_work工作队列里面增加一个工作任务,该任务就是_func。
	 *_func这个任务会需要一些数据作为参数,这个参数就是通过_data传递的
	 */
	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;
	}

	/* 
	 * int gpio_request(unsigned gpio, const char *label)
	 * gpio则为你要申请的哪一个管脚,label则是为其取一个名字
	 */
	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;
	}

	/*
	 *调用gpio_direction_input函数将对应的GPIO设置为输入
	 */
	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);  把spi->irq的PIN值转换为相应的IRQ值,并赋值给变量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;
	}

	/*
	 *在Linux内核中,request_irq() 函数是注册中断服务函数:函数的原型如下:
	 int request_irq (unsigned int irq, 
			void (*handler)(int, void *, struct pt_regs *), 
			unsigned long frags, 
			const char *device, 
			void *dev_id);
			5个参数的含义如下:
			第一个参数irq:申请的硬件中断号;
			第二个参数handler:是一个函数指针,向系统登记的中断处理函数,
		    是一个回调函数,当中断发生时,系统调用这个函数,传入的参数包括中断设备 id,寄存器值。
			第三个参数flags:指定了快速中断或中断共享等中断处理属性。
			第四个参数devices:指定设备驱动程序的名称。
			第五个参数dev_id:传入中断处理程序的参数,可以为NULL,在注册共享中断时,此参数不能为NULL,作为共享中断时的中断区别参数。
		返回值: 
			函数运行正常时返回 0 ,否则返回对应错误的负值。
	 */
	ret = request_irq(irq, mcp251x_irq,IRQF_SAMPLE_RANDOM, DRIVER_NAME, spi);

	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;

	/*
	 *int cdev_add(struct cdev* dev,dev_t num,unsigned int count)
         *num是该设备对应的第一个设备编号,count是应该和该设备关联的设备编号的数量.count经常取1
	 */
	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

/*
 *SPI设备驱动层为用户接口层,其为用户提供了通过SPI总线访问具体设备的接口
 *SPI设备驱动层可以用两个模块来描述,struct spi_driver和struct spi_device。
 *相关的数据结构如下:
  struct spi_driver {  
        int         (*probe)(struct spi_device *spi);  
        int         (*remove)(struct spi_device *spi);  
        void            (*shutdown)(struct spi_device *spi);  
        int         (*suspend)(struct spi_device *spi, pm_message_t mesg);  
        int         (*resume)(struct spi_device *spi);  
        struct device_driver    driver;  
    };
 *Driver是为device服务的,spi_driver注册时会扫描SPI bus上的设备,进行驱动和设备的绑定,
 *probe函数用于驱动和设备匹配时被调用。从上面的结构体注释中我们可以知道,
 *SPI的通信是通过消息队列机制,而不是像I2C那样通过与从设备进行对话的方式。 
*/
static struct spi_driver mcp251x_driver = {
	.driver = {

		/*char* name; 
		 *设备驱动程序的名称。在调用driver_register()往设备驱动程序模型中插入一个新的device_driver对象时,
                 *driver_register()函数会调用bus_add_driver()函数,bus_add_driver()调用kobject_set_name()函数将
                 *name赋给drv>kobj.name或者drv->kobj.k_name。
                 *注:drv为要调用driver_register()注册的device_driver类型的对象。
                 */
		.name	= DRIVER_NAME,

		/*struct bus_type *bus;
                 *指向总线描述符的指针,总线连接所支持的设备。连接的是所有可使用该驱动程序驱动的设备。
                 */
		.bus	= &spi_bus_type,

               /*
                *表示实现设备驱动程序的模块。也就是在该驱动的实现中,如果使用了模块,那么该域就指向你所写的模块
                */
		.owner	= THIS_MODULE,
	},
	
	/*驱动探测函数*/
	.probe	= mcp251x_probe,
	
	/*驱动移除函数
	 *  __devexit_p
	 *#if defined(MODULE) || defined(CONFIG_HOTPLUG)
	 *#define __devexit_p(x) x
	 *#else
	 *#define __devexit_p(x) NULL
	 *#endif
	*/
	.remove	= __devexit_p(mcp251x_remove),

#ifdef CONFIG_PM

	/*suspend 驱动的休眠 */
	.suspend	= mcp251x_suspend,
	
	/*resume 驱动的唤醒 */
	.resume	= mcp251x_resume,
#endif
};

/*
 *初始化驱动函数
 */
static int __init mcp251x_init(void)
{
	int ret;
	/*在驱动初始化的代码里调用class_create为该设备创建一个class,在/sys/class/下创建类目录*/
	can_class = class_create(THIS_MODULE, "can");

	/*IS_ERR 判断返回的指针是错误信息还是实际地址,即指针是否落在最后一页 */
	if (IS_ERR(can_class))

                /*PTR_ERR 将指针转化为错误号  */
		return PTR_ERR(can_class);

        /* 动态分配设备编号,int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name)
         * static dev_t can_devt;
         * 该函数需要传递给它指定的第一个次设备号firstminor(一般为0)
         * 要分配的设备数count,以及设备名,调用该函数后自动分配得到的设备号保存在dev中
         */
	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 删除类*/
		class_destroy(can_class);

		return ret;
	}
        /*
	 *不直接使用原始设备驱动,而是使用包装后的抽象设备驱动spi_driver,
         *间接与原始设备驱动建立联系,并最终通过调用driver_register来注册原始设备驱动
         */
	return spi_register_driver(&mcp251x_driver);
}
module_init(mcp251x_init);

static void __exit mcp251x_exit(void)
{
	/*class_destroy 删除类*/
	class_destroy(can_class);

	/*使用unregister_chrdev_region 被调用用来释放之前申请的设备号*/
	unregister_chrdev_region(can_devt, CAN_DEV_MAX);

        /*注销spi_driver驱动*/
	spi_unregister_driver(&mcp251x_driver);
}
module_exit(mcp251x_exit);


MODULE_DESCRIPTION("MCP251x CAN controller driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Renzhou.Meng");


  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值