📄 s3c44b0-mcp2510.c
字号:
/* * s3c44b0-mcp2510.c * * spi driver for SAMSUNG S3C44B0 * * Author: threewater <threewater@up-tech.com> * Date : $Date: 2003/12/20 22:25:00 $ * * $Revision: 1.1.0.0 $ * * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. * * History: * * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <asm/hardware.h>#include <asm/arch/exio.h>#include <asm/arch/spi.h>#include "s3c44b0-spi.h"#include "s3c44b0-spidev.h"#include "up-can.h"/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( x... ) printk("s3c44b0-mcp2510: " ##x)#else#define DPRINTK( x... )#endif/********************** MCP2510 Pin *********************************/#define MCP2510_CS 0x4 //EXIO2/********************** MCP2510 Instruction *********************************/#define MCP2510INSTR_RESET 0xc0#define MCP2510INSTR_READ 0x03#define MCP2510INSTR_WRITE 0x02#define MCP2510INSTR_RTS 0x80 //request to send#define MCP2510INSTR_RDSTAT 0xa0 //read status#define MCP2510INSTR_BITMDFY 0x05 //bit modify/********************** MCP2510 Regrister *********************************/ // Register offsets into the transmit buffers.#define MCP2510REG_TXBnCTRL 0#define MCP2510REG_TXBnSIDH 1#define MCP2510REG_TXBnSIDL 2#define MCP2510REG_TXBnEID8 3#define MCP2510REG_TXBnEID0 4#define MCP2510REG_TXBnDLC 5#define MCP2510REG_TXBnD0 6#define MCP2510REG_TXBnD1 7#define MCP2510REG_TXBnD2 8#define MCP2510REG_TXBnD3 9#define MCP2510REG_TXBnD4 10#define MCP2510REG_TXBnD5 11#define MCP2510REG_TXBnD6 12#define MCP2510REG_TXBnD7 13#define MCP2510REG_CANSTAT 14#define MCP2510REG_CANCTRL 15 //#define MCP2510LREG_SIDH 0#define MCP2510LREG_SIDL 1#define MCP2510LREG_EID8 2#define MCP2510LREG_EID0 3/******************* Bits in the TXBnCTRL registers.***************************/#define TXB_TXBUFE_M 0x80#define TXB_ABTF_M 0x40#define TXB_MLOA_M 0x20#define TXB_TXERR_M 0x10#define TXB_TXREQ_M 0x08#define TXB_TXIE_M 0x04#define TXB_TXP10_M 0x03#define DLC_MASK 0x0F#define RTR_MASK 0x40#define TXB0CTRL 0x30#define TXB0SIDH 0x31#define TXB1CTRL 0x40#define TXB1SIDH 0x41#define TXB2CTRL 0x50#define TXB2SIDH 0x51#define TXPRIOHIGH 0x03#define TXPRIOHIGHLOW 0x02#define TXPRIOLOWHIGH 0x01#define TXPRIOLOW 0x00#define TXB_EXIDE_M 0x08 // In TXBnSIDL#define TXB_RTR_M 0x40 // In TXBnDLC#define RXB_IDE_M 0x08 // In RXBnSIDL#define RXB_RTR_M 0x40 // In RXBnDLC#define BFPCTRL 0x0C#define B2RTS 0x20#define B1RTS 0x10#define B0RTS 0x08#define B2RTSM 0x04#define B1RTSM 0x02#define B0RTSM 0x01#define TEC 0x1C#define REC 0x1D#define CLKCTRL MCP2510REG_CANCTRL#define RXF0SIDH 0#define RXF0SIDL 1#define RXF0EID8 2#define RXF0EID0 3#define RXF1SIDH 4#define RXF1SIDL 5#define RXF1EID8 6#define RXF1EID0 7#define RXF2SIDH 8#define RXF2SIDL 9#define RXF2EID8 10#define RXF2EID0 11#define RXF3SIDH 16#define RXF3SIDL 17#define RXF3EID8 18#define RXF3EID0 19#define RXF4SIDH 20#define RXF4SIDL 21#define RXF4EID8 22#define RXF4EID0 23#define RXF5SIDH 24#define RXF5SIDL 25#define RXF5EID8 26#define RXF5EID0 27#define RXF_EXIDE_M 0x08#define RXM0SIDH 0x20#define RXM1SIDH 0x24#define CNF3 0x28#define CNF2 0x29#define CNF1 0x2A#define CANINTE 0x2B#define CANINTF 0x2C#define EFLG 0x2D#define TXRTSCTRL 0x0D#define EFLG_RX1OVR 0x80#define EFLG_RX0OVR 0x40#define EFLG_TXBO 0x20#define EFLG_TXEP 0x10#define EFLG_RXEP 0x08#define EFLG_TXWAR 0x04#define EFLG_RXWAR 0x02#define EFLG_EWARN 0x01#define SJW1 0x00#define SJW2 0x40#define SJW3 0x80#define SJW4 0xC0#define BTLMODE_CNF3 0x80#define SAMP1 0x00#define SAMP3 0x40#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 IVRIE 0x80#define WAKIE 0x40#define ERRIE 0x20#define TX2IE 0x10#define TX1IE 0x08#define TX0IE 0x04#define RX1IE 0x02#define RX0IE 0x01#define NO_IE 0x00#define IVRINT 0x80#define WAKINT 0x40#define ERRINT 0x20#define TX2INT 0x10#define TX1INT 0x08#define TX0INT 0x04#define RX1INT 0x02#define RX0INT 0x01#define NO_INT 0x00#define RXB0CTRL 0x60#define RXB1CTRL 0x70#define RXB_RXRDY 0x80#define RXB_RXM1 0x40#define RXB_RXM0 0x20#define RXB_RX_ANY 0x60#define RXB_RX_EXT 0x40#define RXB_RX_STD 0x20#define RXB_RX_STDEXT 0x00#define RXB_RXMx_M 0x60// #define RXB_RXIE_M 0x10#define RXB_RXRTR 0x08 // In RXBnCTRL#define RXB_BUKT 0x04#define RXB_BUKT_RO 0x02#define RXB_FILHIT 0x01#define RXB_FILHIT2 0x04#define RXB_FILHIT1 0x02#define RXB_FILHIT_M 0x07#define RXB_RXF5 0x05#define RXB_RXF4 0x04#define RXB_RXF3 0x03#define RXB_RXF2 0x02#define RXB_RXF1 0x01#define RXB_RXF0 0x00#define CLKEN 0x04#define CLK1 0x00#define CLK2 0x01#define CLK4 0x02#define CLK8 0x03#define MODE_NORMAL 0x00#define MODE_SLEEP 0x20#define MODE_LOOPBACK 0x40#define MODE_LISTENONLY 0x60#define MODE_CONFIG 0xE0#define ABORT 0x10////////////////////////////////////////////////////////////////////////////#define MCP2510_OPEN_INT() do{PCONG |= (3<<12);}while(0) //into EXINT mode#define MCP2510_CLOSE_INT() do{PCONG &= ~(3<<12);}while(0)//into input mode#define IRQ_MCP2510 INT_EINT6#define MCP2510_Enable() do{CLREXIOBIT(MCP2510_CS);udelay(10);}while(0)#define MCP2510_Disable() do{SETEXIOBIT(MCP2510_CS);udelay(10);}while(0)// Start the transmission from one of the tx buffers.#define MCP2510_transmit(address) do{MCP2510_WriteBits(address, TXB_TXREQ_M, TXB_TXREQ_M);}while(0)#define MCP2510_CanRevBuffer 128 //CAN接收缓冲区大小/********************** MCP2510 Candata *********************************/typedef struct { CanData MCP2510_Candata[MCP2510_CanRevBuffer]; //recieve data buffer int nCanRevpos; //recieve buffer pos for queued events int nCanReadpos; //read buffer pos for queued events int loopbackmode; wait_queue_head_t wq; spinlock_t lock;}Mcp2510_DEV;static Mcp2510_DEV mcp2510dev;#define NextCanDataPos(pos) do{(pos)=((pos)+1>=MCP2510_CanRevBuffer? 0: (pos)+1);}while(0)#define DEVICE_NAME "s3c44b0-mcp2510"#define SPIRAW_MINOR 1static int tsMajor = 0;static int opencount=0;#define TRUE 1#define FALSE 0static inline void MCP2510_Reset(void){ MCP2510_Enable(); SendSIOData(MCP2510INSTR_RESET); MCP2510_Disable();}static void MCP2510_Write(int address, int value){ int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_WRITE); SendSIOData((unsigned char)address); SendSIOData((unsigned char)value); MCP2510_Disable(); local_irq_restore(flags);}static unsigned char MCP2510_Read(int address){ unsigned char result; int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_READ); SendSIOData((unsigned char)address); SendSIOData(0); result=ReadSIOData(); MCP2510_Disable(); local_irq_restore(flags); return result;}static unsigned char MCP2510_ReadStatus(void){ unsigned char result; int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_RDSTAT); SendSIOData(0); result=ReadSIOData(); MCP2510_Disable(); local_irq_restore(flags); return result;}static void MCP2510_WriteBits( int address, int data, int mask ){ int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_BITMDFY); SendSIOData((unsigned char)address); SendSIOData((unsigned char)mask); SendSIOData((unsigned char)data); MCP2510_Disable(); local_irq_restore(flags);}/*******************************************\* 序列读取MCP2510数据 *\*******************************************/static void MCP2510_SRead( int address, unsigned char* pdata, int nlength ){ int i; int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_READ); SendSIOData((unsigned char)address); for (i=0; i<nlength; i++) { SendSIOData(0); *pdata=ReadSIOData(); pdata++; } MCP2510_Disable(); local_irq_restore(flags);}/*******************************************\* 序列写入MCP2510数据 *\*******************************************/static void MCP2510_Swrite(int address, unsigned char* pdata, int nlength){ int i; int flags; local_irq_save(flags); MCP2510_Enable(); SendSIOData(MCP2510INSTR_WRITE); SendSIOData((unsigned char)address); for (i=0; i < nlength; i++) { SendSIOData((unsigned char)*pdata); pdata++; } MCP2510_Disable(); local_irq_restore(flags);}/************************************************************\* 设置MCP2510 CAN总线波特率 ** 参数: bandrate为所设置的波特率 ** IsBackNormal为是否要返回Normal模式 *\************************************************************/static void MCP2510_SetBandRate(CanBandRate bandrate, int IsBackNormal){ // // Bit rate calculations. // //Input clock fre=16MHz // In this case, we'll use a speed of 125 kbit/s, 250 kbit/s, 500 kbit/s. // If we set the length of the propagation segment to 7 bit time quanta, // and we set both the phase segments to 4 quanta each, // one bit will be 1+7+4+4 = 16 quanta in length. // // setting the prescaler (BRP) to 0 => 500 kbit/s. // setting the prescaler (BRP) to 1 => 250 kbit/s. // setting the prescaler (BRP) to 3 => 125 kbit/s. // // If we set the length of the propagation segment to 3 bit time quanta, // and we set both the phase segments to 1 quanta each, // one bit will be 1+3+2+2 = 8 quanta in length. // setting the prescaler (BRP) to 0 => 1 Mbit/s. // Go into configuration mode MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG); switch(bandrate){ case BandRate_125kbps: MCP2510_Write(CNF1, SJW1|BRP4); //Synchronization Jump Width Length =1 TQ MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7 MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4 break; case BandRate_250kbps: MCP2510_Write(CNF1, SJW1|BRP2); //Synchronization Jump Width Length =1 TQ MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7 MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4 break; case BandRate_500kbps: MCP2510_Write(CNF1, SJW1|BRP1); //Synchronization Jump Width Length =1 TQ MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7 MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4 break; case BandRate_1Mbps: MCP2510_Write(CNF1, SJW1|BRP1); //Synchronization Jump Width Length =1 TQ MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG3<<3)|SEG2); // Phase Seg 1 = 2, Prop Seg = 3 MCP2510_Write(CNF3, SEG2);// Phase Seg 2 = 1 break; } if(IsBackNormal){ //Enable clock output MCP2510_Write(CLKCTRL, MODE_NORMAL | CLKEN | CLK1); }}/*******************************************\* 读取MCP2510 CAN总线ID ** 参数: address为MCP2510寄存器地址** can_id为返回的ID值 ** 返回值 ** TRUE,表示是扩展ID(29位) ** FALSE,表示非扩展ID(11位) *\*******************************************/static int MCP2510_Read_Can_ID( int address, __u32* can_id){ __u32 tbufdata; unsigned char* p=(unsigned char*)&tbufdata; MCP2510_SRead(address, p, 4); *can_id = (tbufdata<<3)|((tbufdata>>13)&0x7); *can_id &= 0x7ff; if ( (p[MCP2510LREG_SIDL] & TXB_EXIDE_M) == TXB_EXIDE_M ) { *can_id = (*can_id<<2) | (p[MCP2510LREG_SIDL] & 0x03); *can_id <<= 16; *can_id |= tbufdata>>16; return TRUE; } return FALSE;}/***********************************************************\* 读取MCP2510 接收的数据 ** 参数: *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -