📄 sja1000.c
字号:
/* * sja1000.c * Copyright (c) 2001 J黵gen Eder <Juergen.Eder@gmx.de> * * A general chipset driver for CAN cards with SJA1000 (82C200 should work * in CAN 2.0A mode). To use this, the hardware driver is needed (e.g. can200par.o * or elektor_canpar.o) * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define EXPORT_SYMTAB#include <linux/version.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/parport.h>#include <linux/ioctl.h>#include <asm/uaccess.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <linux/time.h>#include "trace.h"#include "sja1000.h"#include "canbus4linux.h"#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifint sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate);int sja1000_set_baudrate_by_constant(struct sja1000_admin *pSja1000Par, unsigned long baudrate);int sja1000_set_acceptance_filter(struct sja1000_admin *pSja1000Par, struct canbus_acceptance_filter *filter);int sja1000_check_chipset(struct sja1000_admin *pSja1000Par);int sja1000_activate_device(struct sja1000_admin *pSja1000Par);int sja1000_init_device(struct sja1000_admin *pSja1000Par);int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par);int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value);int sja1000_get_register(struct sja1000_admin *pSja1000Par, int addresse, int *value);#define NUM_SJA1000_DEVICES 10static struct sja1000_admin sja1000_admin[NUM_SJA1000_DEVICES];#define SJA1000_DECLCHIP(x) \ struct sja1000_access * chip = &((x)->access); \ void * chip_data = (x)->pDeviceParm; \ do {} while (0) // makes the user put ';' after it #define SJA1000_TEST_DECLCHIP(x) \ struct sja1000_access * chip; \ void * chip_data; \ if (!(x)) \ return -ENODEV; \ chip = &((x)->access); \ chip_data = (x)->pDeviceParm; \ do {} while (0) // makes the user put ';' after it/***************************************************************************************/static void sja1000_LockRegister(struct sja1000_admin *pSja1000Par){ spin_lock_irqsave(&pSja1000Par->irq_lock,pSja1000Par->lock_flags);}/***************************************************************************************/static void sja1000_UnLockRegister(struct sja1000_admin *pSja1000Par){ spin_unlock_irqrestore(&pSja1000Par->irq_lock,pSja1000Par->lock_flags);}/***************************************************************************************/static void sja1000_WriteRegister(struct sja1000_admin *pSja1000Par, u8 addr, u8 value){ SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, addr, value); sja1000_UnLockRegister(pSja1000Par);}/***************************************************************************************/static u8 sja1000_ReadRegister(struct sja1000_admin *pSja1000Par, u8 addr){ u8 ret=0; SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); ret = chip->pReadFromRegister(chip_data, addr); sja1000_UnLockRegister(pSja1000Par); return ret;}/***************************************************************************************/static void sja1000_WriteRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr, u8 value){ SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01); chip->pWriteToRegister(chip_data, addr, value); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e); sja1000_UnLockRegister(pSja1000Par);}/***************************************************************************************/static u8 sja1000_ReadRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr){ u8 ret=0; SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01); ret = chip->pReadFromRegister(chip_data, addr); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e); sja1000_UnLockRegister(pSja1000Par); return ret;}/***************************************************************************************/int sja1000_open_device(struct sja1000_admin *pSja1000Par){ int ret; SJA1000_TEST_DECLCHIP(pSja1000Par); ret = chip->pOpenCanDevice(chip_data); sja1000_activate_device(pSja1000Par); return ret;}/***************************************************************************************/int sja1000_close_device(struct sja1000_admin *pSja1000Par){ int ret; SJA1000_TEST_DECLCHIP(pSja1000Par); ret = chip->pCloseCanDevice(chip_data); sja1000_deactivate_device(pSja1000Par); return ret;}/***************************************************************************************/int sja1000_init_device(struct sja1000_admin *pSja1000Par){ SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Init Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 0, 0x08); // Acceptance Filter Mode: single sja1000_WriteRegisterRR(pSja1000Par, 31, 0x80 | sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican einschalten sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegisterRR(pSja1000Par, 12, 0); // error code capture sja1000_WriteRegisterRR(pSja1000Par, 13, 96); // error warning limit sja1000_WriteRegisterRR(pSja1000Par, 14, 0x00); // RX error counter sja1000_WriteRegisterRR(pSja1000Par, 15, 0x00); // TX error counter sja1000_ReadRegister(pSja1000Par, 3); } else { TRACE("Init BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 31, 0x7f & sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican ausschalten sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 10, 0x25); // Bit ID3 bis ID10 sja1000_WriteRegister(pSja1000Par, 11, 0x88); // Bit ID0 bis ID2, RTR-Flag, Data-Length-Code } return 0;}/***************************************************************************************/int sja1000_activate_device(struct sja1000_admin *pSja1000Par){ SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Activate Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 0, 0x00); // Reset Request =0 sja1000_ReadRegister(pSja1000Par, 3); } else { TRACE("Activate BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 0, 0x3e); // Reset Request =0 } return 0;}/***************************************************************************************/int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par){ SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Activate Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 4,0); // IRQ's } else { TRACE("Activate BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 0,0); // Reset Request=1 + alle IRQs freigeben } return 0;}/***************************************************************************************/static int iSetSJA1000Baudrate(struct sja1000_admin *pSja1000Par){ u8 tmp; unsigned long wbaud; long bpr,ts1,ts2; int ts2array[]={2,3,4,5,1,6,7,0}; int x; long testwert,neutest=50; INFO_TRACE("Calculating baudrate for frequency %d",pSja1000Par->access.chipset_frequency); wbaud = pSja1000Par->iBaudrate; if (wbaud < 5000) wbaud = 5000; if (wbaud > 2000000) wbaud = 2000000; pSja1000Par->iBaudrate = wbaud; testwert = pSja1000Par->access.chipset_frequency/(wbaud*2); while(neutest > 0) { for(x=0;x<sizeof(ts2array)/sizeof(int);x++) { ts2 = ts2array[x]; for(ts1=0x0f;ts1>=0;ts1--) { if ((testwert % (ts1+ts2+3)) == 0) { bpr = testwert/(ts1+ts2+3)-1; if ((bpr >= 0) && (bpr < 0x40)) { bpr |= 0x40; // SJW.0 setzen tmp = (u8)((ts2 << 4) + ts1); TRACE("%ld ts2 %ld ts1 %ld BPR0 0x%lx BPR1 0x%x",testwert,ts2, ts1, bpr,tmp); sja1000_WriteRegisterRR(pSja1000Par, 6, (u8)bpr); sja1000_WriteRegisterRR(pSja1000Par, 7, tmp); return 1; } } } } testwert++; neutest--; } TRACE("Can't set baudrate"); return 0;}/***************************************************************************************/int sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate){ if(!pSja1000Par) return -ENODEV; pSja1000Par->iBaudrate = baudrate; if(!iSetSJA1000Baudrate(pSja1000Par)) { return -EINVAL; } return 0;}/***************************************************************************************/const unsigned long baudrate_list[]={ 20000, 50000, 100000, 125000, 150000, 200000, 500000, 1000000, 0};int sja1000_get_properties(struct sja1000_admin *pSja1000Par, struct canbus_properties *props){ static const int basiccan[]= { CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION, CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY,0 }; static const int pelican[]= { CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION, CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY, CANBUS_CMD_SELF_RECEPTION_REQUEST,CANBUS_CMD_LISTEN_ON, CANBUS_CMD_LISTEN_OFF,0 }; int t; props->min = 20000; props->max = 1000000; props->chipset_flags = pSja1000Par->access.bCanChipsetFlags; props->number_baudrates = 0; props->number_registers = 128*2; /* This function is called by an application to get all provided commands. */ if(!pSja1000Par) return -ENODEV; if(pSja1000Par->bCan_2B) { for(t=0;pelican[t];t++) props->commands[t] = pelican[t]; props->number_commands = t; } else { for(t=0;basiccan[t];t++) props->commands[t] = basiccan[t]; props->number_commands = t; } for(t=0;baudrate_list[t] && (t<CANBUS_NUMBER_OF_CONSTANT_BAUDRATES);t++) props->baudrates[t] = baudrate_list[t]; //props->number_baudrates = t; return 0;}/***************************************************************************************/int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value){ int ret = -ENOSYS; /* The SJA1000 has 128 normal register and 128 'reset mode' register (in PELICAN mode) * To get a hardware abstraction in above layers, this function accepts following * addresses: * 0...7f = normal mode registers * 80..ff = reset mode register 0...7f */ if(pSja1000Par) { if((addresse >= 0x80) && (addresse <= 0xff)) // RESET Mode ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -