⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em104_can.c

📁 在linux2.6.14下的can的驱动
💻 C
字号:

#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/arch/regs-mem.h>

#include "trace.h"
#include "sja1000.h"
#include "canbus4linux.h"

MODULE_LICENSE("GPL");

static void em104_sja1000_writereg(void * data, u8 reg, u8 val);
static u8 em104_sja1000_readreg(void * data, u8 reg);
static int em104_sja1000_register_isr(void * data, sja1000_isr chip_isr, struct sja1000_admin * chip_isr_data);
static int em104_sja1000_unregister_isr(void * data);
static int em104_sja1000_open(void * data);
static int em104_sja1000_close(void * data);


struct EM104_SJA1000_CHIP
{
	unsigned long			addr;
	unsigned long			data;
	char					name[MAX_DEVICE_NAME_LENGTH];
	int						num;
	spinlock_t				lock;
	int						open;
	sja1000_isr				chip_isr;
	struct sja1000_admin *	chip_isr_data;
};

static struct EM104_SJA1000_CHIP chip[2] = {
	[0] = {
		addr:		(0xE0000000+0x00800000),
		data:		(0xE0000000+0x00a00000),
		name:		"can0",
		num:		-1,
		lock:		SPIN_LOCK_UNLOCKED,
		open:		0
	},
	[1] = {
		addr:		(0xE0000000+0x00800000),
		data:		(0xE0000000+0x00c00000),
		name:		"can1",
		num:		-1,
		lock:		SPIN_LOCK_UNLOCKED,
		open:		0		
	}
};

static struct sja1000_access access[2] = {
	[0] = {
		pOpenCanDevice:				em104_sja1000_open,
		pCloseCanDevice:			em104_sja1000_close,
		pWriteToRegister:			em104_sja1000_writereg,
		pReadFromRegister:			em104_sja1000_readreg,
		pRegisterIsr:				em104_sja1000_register_isr,
		pUnregisterIsr:				em104_sja1000_unregister_isr,
		bCanChipsetFlags:			CANBUS_CFS_CAN_2_0_A | CANBUS_CFS_EXT_FRAME,
		chipset_frequency:			16000000,
		output_control_register:	0x1b
	},
	[1] = {
		pOpenCanDevice:				em104_sja1000_open,
		pCloseCanDevice:			em104_sja1000_close,
		pWriteToRegister:			em104_sja1000_writereg,
		pReadFromRegister:			em104_sja1000_readreg,
		pRegisterIsr:				em104_sja1000_register_isr,
		pUnregisterIsr:				em104_sja1000_unregister_isr,
		bCanChipsetFlags:			CANBUS_CFS_CAN_2_0_A | CANBUS_CFS_EXT_FRAME,
		chipset_frequency:			16000000,
		output_control_register:	0x1b		
	}
};


static void em104_sja1000_writereg(void * data, u8 reg, u8 val)
{
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) data;
	TRACE("writereg(0x%2.2x,0x%2.2x)", reg, val);
	outb(reg, self->addr);
	outb(val, self->data);
}

static u8 em104_sja1000_readreg(void * data, u8 reg)
{	
	u8 val;
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) data;
	outb(reg, self->addr);
	val = inb(self->data);
	TRACE("readreg(0x%2.2x) = 0x%2.2x", reg, val);
	return val;
}

static int em104_sja1000_register_isr(void * data, sja1000_isr chip_isr, struct sja1000_admin * chip_isr_data)
{
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) data;

	TRACE("register_isr()");

	if (!self)
		return -EINVAL;

	self->chip_isr		= chip_isr;
	self->chip_isr_data	= chip_isr_data;

	return 0;
}

static int em104_sja1000_unregister_isr(void * data)
{
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) data;

	TRACE("unregister_isr()");

	if (!self)
		return -EINVAL;

	self->chip_isr		= 0;
	self->chip_isr_data	= 0;

	return 0;
}

static int em104_sja1000_open(void * data)
{
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) data;
	int err;

	TRACE("open()");
	spin_lock(&self->lock);
	do {
		if (self->open) {
			err = -EBUSY;
			break;
		}
		self->open++;
		em104_sja1000_writereg(self, 0x1e, 0x00);		// reset, check it!!
	} while (0);
	spin_unlock(&self->lock);	
	return 0;
}

static int em104_sja1000_close(void * data)
{
	TRACE("close()");
	return 0;
}

static irqreturn_t em104_sja1000_isr(int irq, void *dev_id, struct pt_regs *regs)
{
	struct EM104_SJA1000_CHIP * self = (struct EM104_SJA1000_CHIP *) dev_id;
	
	static unsigned char vector;
	vector = inb(0xE0000000 + 0x02200000);
	if((vector&0x10)==0x00)
	{
		TRACE("can0 isr()");
		if (!self)
			return IRQ_NONE;
		if (self->chip_isr)
			self->chip_isr(self,self->chip_isr_data);
	}
	else if((vector&0x20)==0x00)
	{
		TRACE("can1 isr()");
		if (!self)
			return IRQ_NONE;

		if (self->chip_isr)
			self->chip_isr(self,self->chip_isr_data);
	}
	return IRQ_HANDLED;	
}

int __init em104_sja1000_init(void)
{
	unsigned int bswcon = inl((unsigned int)S3C2410_BWSCON);
	bswcon = (bswcon & 0xFFFCFFFF) | 0x00000000;
	outl(bswcon,(unsigned int)S3C2410_BWSCON);
	bswcon = inl((unsigned int)S3C2410_BWSCON);
	
	outb(~0xFF,0xE0000000+0x02600000);
	
	set_irq_type(IRQ_EINT9,IRQT_FALLING);
	if(request_irq(IRQ_EINT9, em104_sja1000_isr, SA_SHIRQ, "can isr", &chip[0]))
	{
		TRACE("request_irq(%d) failed", IRQ_EINT9);
		return -ENOMEM;
	}
	
	TRACE("registering device %s", chip[0].name);
	chip[0].num = sja1000_register_device(chip[0].name, CANBUS4LINUX_VERSION, &chip[0], &access[0], 0, 0);
	if (chip[0].num == -1) {
		TRACE("can0 sja1000_register_device() failed");
		return -ENOMEM;
	}
	
	if(request_irq(IRQ_EINT9, em104_sja1000_isr, SA_SHIRQ, "can isr", &chip[1]))
	{
		TRACE("request_irq(%d) failed", IRQ_EINT9);
		return -ENOMEM;
	}
	
	TRACE("registering device %s", chip[1].name);
	chip[1].num = sja1000_register_device(chip[1].name, CANBUS4LINUX_VERSION, &chip[1], &access[1], 0, 1);
	if (chip[1].num == -1) {
		TRACE("can1 sja1000_register_device() failed");
		return -ENOMEM;
	}	
	return 0;
}

void __exit em104_sja1000_cleanup(void)
{
	free_irq(IRQ_EINT9, &chip[0]);
}

module_init(em104_sja1000_init);
module_exit(em104_sja1000_cleanup);
MODULE_AUTHOR("JJJ <jiangjj@embedinfo.com>");
MODULE_DESCRIPTION("CAN driver for EM104 SJA1000");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -