📄 em104_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_B | 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_B | 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; } 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[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; } 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 + -