i2c驱动--驱动框架
来源:互联网 发布:宠宠熊淘宝店卖假货 编辑:程序博客网 时间:2024/04/29 23:50
I2C驱动框架
App :open 、read、 write
驱动:
drv_open 、drv_read 、drv_write :I2C设备驱动:包含数据含义
——————————–
I2C总线驱动程序:①识别 ② 提供读写函数:不知道数据含义
硬件: AT24C02 At24C08
I2c-s3c2410.c(linux-2.6.22.6\drivers\i2c\busses)
一、平台注册及平台设备的描述
平台注册:
static int __init i2c_adap_s3c_init(void){ int ret; ret = platform_driver_register(&s3c2410_i2c_driver);//注册2410,返回ret if (ret == 0) { ret = platform_driver_register(&s3c2440_i2c_driver);//没有注册2410,注册2440,返回ret if (ret) platform_driver_unregister(&s3c2410_i2c_driver);//卸载2410 } return ret;}
注意:
(1)这里只是调用了平台驱动注册函数注册了一个i2c的平台驱动s3c24xx_i2c_driver,这个驱动是一个platform_driver的结构体变量。不是i2c_driver结构体,因为i2c_driver是对设备的驱动,而这里对控制器的驱动要使用platform_driver。区分开总线驱动和设备驱动。
(2)这个驱动是基于platform总线的, 设备信息的部分在板级文件i2c-boardinfo.c中描述并作为platform_device随内核启动被注册, 所以控制器驱动在系统启动的时候就可以工作了。
描述:
/* device driver for platform bus bits */static struct platform_driver s3c2440_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, .resume = s3c24xx_i2c_resume, .driver = { .owner = THIS_MODULE, .name = "s3c2440-i2c", },};
s3c2440_i2c_driver遵循platform编写,它的所有信息都要在一个platform_driver中描述, 分析也是围绕这个对象展开。
二、调用s3c24xx_i2c_probe
当内核中有同名的平台设备s3c2440-i2c(根据.id_table = s3c24xx_driver_ids来进行匹配),调用s3c24xx_i2c_probe。
http://blog.csdn.net/duzanuolu/article/details/63533696 参考这篇博客
一旦匹配上, 分析流程就会有点变化, 驱动开发都是基于面向对象的思想的, 内核虽然给我们封装了很多”类”, 但当我们开发一个具体的驱动的时候, 还是要对其进行”继承”, 进而创建针对具体设备的资源对象, 资源对象管理着驱动中诸多函数的共用资源, 是整个驱动运行过程中资源管理者与桥梁, 主要包括:内核类+资源(io, irq,时钟, 寄存器)+状态表示+其他,所以, 设计驱动的工作中很重要的一个工作就是”设计资源类”. 下面就是三星设计的类, 把次要的部分剔除了。
资源类
struct s3c24xx_i2c { spinlock_t lock; wait_queue_head_t wait; struct i2c_msg *msg;//收到的i2c-core.c发送过来的i2c_msg对象数组首地址 unsigned int msg_num;//i2c_msg数组的元素个数 unsigned int msg_idx;//i2c_msg数组元素的索引 unsigned int msg_ptr; unsigned int tx_setup; enum s3c24xx_i2c_state state;//当前控制器的状态, 用枚举量表示STATE_IDLE, STATE_START,STATE_READ,STATE_WRITE,STATE_STOP void __iomem *regs; struct clk *clk;//时钟 struct device *dev;//属于device, 按照device来管理 struct resource *irq;//中断 struct resource *ioarea; struct i2c_adapter adap;//构造并使用的i2c_adapter对象};
s3c24xx_i2c_probe的主要代码注释:
/* s3c24xx_i2c_probe * * called by the bus driver when a suitable device is found*/static int s3c24xx_i2c_probe(struct platform_device *pdev){ ... /* find the clock and enable it */ i2c->dev = &pdev->dev; i2c->clk = clk_get(&pdev->dev, "i2c");//使能i2c时钟 ... ret = i2c_add_adapter(&i2c->adap);//将构造的adapter对象注册到内核 if (ret < 0) { dev_err(&pdev->dev, "failed to add bus to i2c core\n"); goto err_irq; } }
三、算法实现
注:需要详细注解以后!
static struct s3c24xx_i2c s3c24xx_i2c = { ... .algo = &s3c24xx_i2c_algorithm, ... }
i2c_algorithm
static const struct i2c_algorithm s3c24xx_i2c_algorithm = { .master_xfer = s3c24xx_i2c_xfer, .functionality = s3c24xx_i2c_func,};
核心:
s3c24xx_i2c_xfer
/* s3c24xx_i2c_xfer * * first port of call from the i2c bus code when an message needs * transferring across the i2c bus.*/static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num){ struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; int retry; int ret; for (retry = 0; retry < adap->retries; retry++) { ret = s3c24xx_i2c_doxfer(i2c, msgs, num); if (ret != -EAGAIN) return ret; dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); udelay(100); } return -EREMOTEIO;}
s3c24xx_i2c_doxfer
/* s3c24xx_i2c_doxfer * * this starts an i2c transfer*/static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num){ unsigned long timeout; int ret; ret = s3c24xx_i2c_set_master(i2c); if (ret != 0) { dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); ret = -EAGAIN; goto out; } spin_lock_irq(&i2c->lock); i2c->msg = msgs; i2c->msg_num = num; i2c->msg_ptr = 0; i2c->msg_idx = 0; i2c->state = STATE_START; s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); spin_unlock_irq(&i2c->lock); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); ret = i2c->msg_idx; /* having these next two as dev_err() makes life very * noisy when doing an i2cdetect */ if (timeout == 0) dev_dbg(i2c->dev, "timeout\n"); else if (ret != num) dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); /* ensure the stop has been through the bus */ msleep(1); out: return ret;}
s3c24xx_i2c_message_start
/* s3c24xx_i2c_message_start * * put the start of a message onto the bus */static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, struct i2c_msg *msg){ unsigned int addr = (msg->addr & 0x7f) << 1; unsigned long stat; unsigned long iiccon; stat = 0; stat |= S3C2410_IICSTAT_TXRXEN; if (msg->flags & I2C_M_RD) { stat |= S3C2410_IICSTAT_MASTER_RX; addr |= 1; } else stat |= S3C2410_IICSTAT_MASTER_TX; if (msg->flags & I2C_M_REV_DIR_ADDR) addr ^= 1; // todo - check for wether ack wanted or not s3c24xx_i2c_enable_ack(i2c); iiccon = readl(i2c->regs + S3C2410_IICCON); writel(stat, i2c->regs + S3C2410_IICSTAT); dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); writeb(addr, i2c->regs + S3C2410_IICDS); /* delay here to ensure the data byte has gotten onto the bus * before the transaction is started */ ndelay(i2c->tx_setup); dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); writel(iiccon, i2c->regs + S3C2410_IICCON); stat |= S3C2410_IICSTAT_START; writel(stat, i2c->regs + S3C2410_IICSTAT);}
总线驱动和设备驱动的总体框架:
i2c_add_driver
①将i2c_driver放入链表
② 从adapter 链表取出适配器,调用drv的 .attach_adapter
③ .attach_adapter调用i2c_probe (adapter,设备地址,function)
1.用adapter的.master_xfer发信号,确定有无该设备
2.若有则调用function
i2c_add_adapter
①放入链表
②调用drv的.attach_adapter
③ .attach_adapter调用i2c_probe (adapter,设备地址,function)
1.用adapter的.master_xfer发信号,确定有无该设备
2.若有则调用function
整个流程通过eeprom.c(drivers/i2c/chips)来分析:
- i2c驱动--驱动框架
- I2C驱动框架
- i2c驱动框架
- linux驱动之I2C驱动框架
- I2C子系统驱动架构 - 驱动框架
- i2c 驱动举例框架分析
- I2C驱动总体框架图
- SylixOS I2C驱动框架浅析
- SylixOS I2C驱动框架概述
- SylixOS I2C驱动框架图
- I2C设备驱动(三)--linux i2c驱动框架
- i2c驱动
- I2C驱动
- I2C 驱动
- I2C驱动
- i2c驱动
- I2C驱动
- I2C驱动
- 17. 数据结构进阶十七排序实现之归并排序
- VS 排序思考与实现——动态规划(四)
- 类java作业
- 【bzoj 2038】小Z的袜子(hose) [2009国家集训队]
- Android中.aar文件如何生成?
- i2c驱动--驱动框架
- initial job has not accepted any resources
- [BZOJ1305][CQOI2009]跳舞(二分答案+最大流)
- kettle数据抽取安装及基本操作总结
- 18. 数据结构进阶十八排序实现之快速排序
- 【codevs 3287】货车运输
- 170924 逆向-Reversing.kr(EasyCrack、EasyKeygen、EasyUnpack)
- ObjectMapper对象(json格式转换)
- Ajax的使用四大步骤