2014-04-12 i2c总线驱动程序__
来源:互联网 发布:电脑设置闹钟软件 编辑:程序博客网 时间:2024/06/02 02:14
实验描述:
i2c总线驱动程序
i2c设备驱动程序读写EEPROM
注意事项:
如何确定i2c总线编号:cat /sys/class/i2c-dev/i2c-0/name
内核版本:
Linux 2.6.38
开发板:
Mini 6410
i2c_my_bus.c
#include <linux/init.h> #include <linux/module.h> #include <linux/device.h>#include <linux/cdev.h> #include <linux/i2c.h>#include <linux/fs.h> #include <asm/uaccess.h>#include <linux/delay.h>#include <linux/clk.h>#include <asm/irq.h>#include <linux/time.h>#include <linux/interrupt.h>#include <linux/io.h>#define PRINTK printk//#define PRINTK(...) enum s3c6410_i2c_state {STATE_IDLE,STATE_START,STATE_READ,STATE_WRITE,STATE_STOP};struct s3c6410_i2c_regs {unsigned int iic_con;unsigned int iic_stat;unsigned int iic_add;unsigned int iic_ds;unsigned int iic_lc;};struct s3c6410_i2c{struct i2c_adapter adapter;spinlock_tlock;wait_queue_head_twait;struct clk*clk;enum s3c6410_i2c_state s3c6410_i2c_state;struct s3c6410_i2c_regs *s3c6410_i2c_regs;unsigned long *gpbcon;struct i2c_msg *msgs;int msn_num;int cur_msg;int cur_ptr;int state;int err;};struct s3c6410_i2c my_s3c6410_i2c;static void s3c6410_i2c_start(void){my_s3c6410_i2c.state = STATE_START;if (my_s3c6410_i2c.msgs->flags & I2C_M_RD) /* read */{my_s3c6410_i2c.s3c6410_i2c_regs->iic_ds = my_s3c6410_i2c.msgs->addr << 1;//iic data storemy_s3c6410_i2c.s3c6410_i2c_regs->iic_stat = 0b10110000; // master receive, enable Tx/Rx, send start signal}else /* write */{my_s3c6410_i2c.s3c6410_i2c_regs->iic_ds = my_s3c6410_i2c.msgs->addr << 1;my_s3c6410_i2c.s3c6410_i2c_regs->iic_stat = 0b11110000; // master transmit, enable Tx/Rx, send start signal}}static void s3c6410_i2c_stop(int err){my_s3c6410_i2c.state = STATE_STOP;my_s3c6410_i2c.err = err;PRINTK("iic STATE_STOP, err = %d\n", err);if (my_s3c6410_i2c.msgs->flags & I2C_M_RD) /* read */{// master receive, enable Tx/Rx, send P signalmy_s3c6410_i2c.s3c6410_i2c_regs->iic_stat = 0b10010000;my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = 0b10101111;ndelay(50); //wait}else {// master transmit, enable Tx/Rx, send P signal?my_s3c6410_i2c.s3c6410_i2c_regs->iic_stat = 0b11010000;my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = 0b10101111;ndelay(50); }/* wait the queue*/wake_up(&my_s3c6410_i2c.wait);}static int s3c6410_master_xfer(struct i2c_adapter * adapter, struct i2c_msg * msg, int num){printk(KERN_ALERT"s3c6410_i2c_xfer time i2c_msg addr:%d, buf first:%d\n", msg->addr, msg->buf[0]);//we can get the messages;unsigned long timeout;/* send num messages*/my_s3c6410_i2c.msgs = msg;my_s3c6410_i2c.msn_num = num;my_s3c6410_i2c.cur_msg = 0;my_s3c6410_i2c.cur_ptr = 0;my_s3c6410_i2c.err = -ENODEV;s3c6410_i2c_start();timeout = wait_event_timeout(my_s3c6410_i2c.wait, (my_s3c6410_i2c.state == STATE_STOP), HZ * 5);if (0 == timeout){printk("s3c6410_i2c_xfer time out\n");return -ETIMEDOUT;}else{return my_s3c6410_i2c.err;}}static u32 s3c6410_functionality (struct i2c_adapter * adapter){return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;}struct i2c_algorithm s3c6410_algorithm = {.master_xfer = s3c6410_master_xfer,.functionality = s3c6410_functionality,};static int isLastMsg(void){return (my_s3c6410_i2c.cur_msg == my_s3c6410_i2c.msn_num - 1);}static int isEndData(void){return (my_s3c6410_i2c.cur_ptr >= my_s3c6410_i2c.msgs->len);}static int isLastData(void){return (my_s3c6410_i2c.cur_ptr == (my_s3c6410_i2c.msgs->len - 1));}static irqreturn_t s3c6410_iic_xfer(int irq, void *dev){unsigned int iicSt;iicSt = my_s3c6410_i2c.s3c6410_i2c_regs->iic_stat; if(iicSt & 0b1000)printk("sorry Bus arbitration failed\n\r"); switch (my_s3c6410_i2c.state){case STATE_START : /* send S signal and device address, will produce interrupt and we will deal*/{PRINTK("Start\n");if (iicSt & 0b0001)//check is ack{s3c6410_i2c_stop(-ENODEV);break;}if (isLastMsg() && isEndData()){s3c6410_i2c_stop(0);break;}//go to next stateif (my_s3c6410_i2c.msgs->flags & I2C_M_RD) /* read */{my_s3c6410_i2c.state = STATE_READ;goto next_read;}else{my_s3c6410_i2c.state = STATE_WRITE;}}case STATE_WRITE:{PRINTK("STATE_WRITE\n");if (iicSt & 0b0001)//if the last is ack, we will stop{s3c6410_i2c_stop(-ENODEV);break;}if (!isEndData()) //we still have messages to transmit{my_s3c6410_i2c.s3c6410_i2c_regs->iic_ds = my_s3c6410_i2c.msgs->buf[my_s3c6410_i2c.cur_ptr];//pointer the data bufPRINTK("cur:%d, len: %d, writeBuffer:%d\n", my_s3c6410_i2c.cur_ptr, my_s3c6410_i2c.msgs->len, my_s3c6410_i2c.msgs->buf[my_s3c6410_i2c.cur_ptr]);my_s3c6410_i2c.cur_ptr++;// we should wait a little time, which can enable data to be occureed int SDAndelay(50);my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = 0b10101111;// recover iic transmitbreak;}else if (!isLastMsg()){//we will deal next messagemy_s3c6410_i2c.msgs++;my_s3c6410_i2c.cur_msg++;my_s3c6410_i2c.cur_ptr = 0;my_s3c6410_i2c.state = STATE_START;//send S signal and device addresss3c6410_i2c_start();//we will do a new transmitbreak;}else{//last message and last datas3c6410_i2c_stop(0);break;}break;}case STATE_READ:{//read datamy_s3c6410_i2c.msgs->buf[my_s3c6410_i2c.cur_ptr] = my_s3c6410_i2c.s3c6410_i2c_regs->iic_ds;PRINTK("cur:%d, len: %d, Read Buffer: %d\n", my_s3c6410_i2c.cur_ptr, my_s3c6410_i2c.msgs->len, my_s3c6410_i2c.msgs->buf[my_s3c6410_i2c.cur_ptr]);my_s3c6410_i2c.cur_ptr++;next_read:if (!isEndData()) //if we still have data to read, we should continue{if (isLastData()) //if this data is the last, we will have no ack{my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = 0x00101111; // diable ack signalPRINTK("last data no ack\n");}else{my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = 0b10101111; // recover iic transmit, next data we will receive ackPRINTK("last data have ack\n");}break;}else if (!isLastMsg()){//we will deal next messagemy_s3c6410_i2c.msgs++;my_s3c6410_i2c.cur_msg++;my_s3c6410_i2c.cur_ptr = 0;my_s3c6410_i2c.state = STATE_START;//send S signal and device addresss3c6410_i2c_start();break;}else{//last message and last datas3c6410_i2c_stop(0);break;}break;}default: break;}//clear interrupt, so we can restore deal my_s3c6410_i2c.s3c6410_i2c_regs->iic_con &= ~(1<<4);return IRQ_HANDLED;}static int i2c_bus_init(void) { strlcpy(my_s3c6410_i2c.adapter.name, "s3c6410-i2c", sizeof(my_s3c6410_i2c.adapter.name));my_s3c6410_i2c.adapter.algo = &s3c6410_algorithm;my_s3c6410_i2c.adapter.owner = THIS_MODULE;my_s3c6410_i2c.clk = clk_get(NULL, "i2c");clk_enable(my_s3c6410_i2c.clk);// set the hadware paramtermy_s3c6410_i2c.gpbcon = (volatile unsigned long *)ioremap(0x7F008020, sizeof(unsigned int)); my_s3c6410_i2c.s3c6410_i2c_regs = ioremap(0x7F004000, sizeof(struct s3c6410_i2c_regs));//very impotant*my_s3c6410_i2c.gpbcon &= ~(0b1111 << 20 | 0b1111<<24);//enable the i2cscl and i2csda*my_s3c6410_i2c.gpbcon |= (0b0010 << 20 | 0b0010<<24);my_s3c6410_i2c.s3c6410_i2c_regs->iic_con = (1<<7 ) | (0 << 6 ) | (1<<5 ) | (0xf<<3);my_s3c6410_i2c.s3c6410_i2c_regs->iic_add = 0x10;my_s3c6410_i2c.s3c6410_i2c_regs->iic_stat = 0x10;//enable Rx/Txinit_waitqueue_head(&my_s3c6410_i2c.wait);int err;err = request_irq(IRQ_IIC, s3c6410_iic_xfer, 0, "s3c6410_iic_bus", 0); if(err){ PRINTK(KERN_ALERT"can not obtain irq!\n");goto err_irq; } i2c_add_adapter(&my_s3c6410_i2c.adapter);PRINTK(KERN_ALERT"init!\n");return 0; err_irq:iounmap(my_s3c6410_i2c.s3c6410_i2c_regs);iounmap(my_s3c6410_i2c.gpbcon);clk_disable(my_s3c6410_i2c.clk);clk_put(my_s3c6410_i2c.clk);return err;} static int i2c_bus_exit(void) { iounmap(my_s3c6410_i2c.s3c6410_i2c_regs);iounmap(my_s3c6410_i2c.gpbcon);free_irq(IRQ_IIC, NULL);clk_disable(my_s3c6410_i2c.clk);clk_put(my_s3c6410_i2c.clk);i2c_del_adapter(&my_s3c6410_i2c.adapter);PRINTK(KERN_ALERT"exit!\n");return 0; } module_init(i2c_bus_init); module_exit(i2c_bus_exit);MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("S3C6410 I2C Bus driver");MODULE_AUTHOR("Books, <uppour@sina.cn>");
0 0
- 2014-04-12 i2c总线驱动程序__
- Linux I2C总线驱动程序
- I2C总线驱动程序
- I2C总线驱动程序的实现
- 51单片机I2C总线驱动程序
- I2C总线 驱动程序设计 --- EEPROM 驱动设计
- 2014-04-17 nand flash驱动程序__
- I2C总线及EEPROM的Linux驱动程序的设计
- 2014-04-19 块设备驱动程序(模拟内存)__
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- i2c总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- 黑马程序员-------IO流
- 线性表、栈、队列的链式存储结构
- VC打印机编程之两篇有用的文章获取打印机与打印作业的状态和设置打印机模式并预览打印
- 【Win7旗舰版系统下载 官方MSDN原版】无第三方软件 纯净32&64位安装教程
- JSP(5):cookie技术
- 2014-04-12 i2c总线驱动程序__
- springmvc注解配置例子的实例代码下载
- IOS推送通知实现步骤
- c标签导入问题
- 1048576玩转 百万数据POI导出
- 解决网络会计中存在问题的对策
- 两个脑残的对话
- 2018
- 汇编跳转指令