54 OrangePi linux内核里的i2c控制器驱动
来源:互联网 发布:veket linux安装 编辑:程序博客网 时间:2024/05/29 09:12
在全志H3平台里的”TWI Controller”就是I2C控制器. 共有4个i2c控制器
script.bin里的i2c控制器配置 :[twi0]twi_used = 1twi_scl = port:PA11<2><default><default><default>twi_sda = port:PA12<2><default><default><default>[twi1]twi_used = 1twi_scl = port:PA18<3><default><default><default>twi_sda = port:PA19<3><default><default><default>[twi2]twi_used = 0twi_scl = port:PE12<3><default><default><default>twi_sda = port:PE13<3><default><default><default>
在linux内核里控制器的驱动是由芯片厂商负责, 而且控制器的驱动都是平台驱动来的.需要用平台设备来描述i2c控制器的硬件信息,如控制器的配置寄存器基地址, 中断号等. 在内核里,可能只会驱动好部分控制器.如SOC里共有4个控制器,需要4个平台设备来分别描述每个控制器的硬件资源, 内核里有可能只写两个相关的平台设备,如需用额外两个控制器,我们则需用平台设备描述好额外两个控制器才可以.
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- Device Drivers ---> <*> I2C support ---> I2C Hardware Bus support ---> <*> SUNXI I2C controller //全志twi控制器的驱动 <*> I2C device interface //选上此项,i2c控制器驱动好后会在/dev目录下有设备文件i2c-*, 供应用程序调用控制器用. 我们也可以通过产生的设备文件得知相应的控制器是否驱动好
/////////////////////////////
控制器的驱动源码在”drivers/i2c/busses/i2c-sunxi.c”
全志控制器的驱动代码不是很规范,控制器的平台驱动与平台设备都在i2c-sunxi.c里,并没有按驱动模型分层的实现.
1589 subsys_initcall(sunxi_i2c_adap_init); //初始化函数static int __init sunxi_i2c_adap_init(void){ ... sunxi_twi_device_scan(); //初始化平台设备 sunxi_twi_device[SUNXI_TWI_NUM] twi_chan_cfg(sunxi_twi_pdata); //根据script.bin里的twi_used子键的配置来用全局变量twi_used_mask来记录相应的控制器是否使用.#ifdef CONFIG_EVB_PLATFORM //此宏成立 for (i=0; i<SUNXI_TWI_NUM; i++) //SUNXI_TWI_NUM是表示twi控制器的个数, 现内核里宏的值是3#else i = CONFIG_TWI_CHAN_NUM; /* In FPGA, only one channel is available. */#endif { if (twi_chan_is_enable(i)) { //如果第i个twi控制器需要使用,则注册相应的平台设备. I2C_DBG("Sunxi I2C init channel %d \n", i); ret = platform_device_register(&sunxi_twi_device[i]); ... } if (twi_used_mask) //只有一个以上的控制器的平台设备是使用,则注册控制器的平台驱动 return platform_driver_register(&sunxi_i2c_driver); // sunxi_i2c_driver是控制器的平台驱动 ... return 0;}
内核里分别用三个数组来表示每个控制器的资源,平台数据,平台设备.1378 static struct resource sunxi_twi_resources[SUNXI_TWI_NUM * SUNXI_TWI_RES_NUM];1379 static struct sunxi_i2c_platform_data sunxi_twi_pdata[SUNXI_TWI_NUM];1380 static struct platform_device sunxi_twi_device[SUNXI_TWI_NUM];
1382 static void sunxi_twi_device_scan(void) //初始化平台设备 sunxi_twi_device[SUNXI_TWI_NUM]1383 {1384 int i; ...1389 1390 for (i=0; i<SUNXI_TWI_NUM; i++) { // 初始化每个平台设备,及它的资源,平台数据。 i表示第几个控制器 //准备平台设备所用的资源. twi控制器的配置寄存器的开始地址,结束地址.1391 sunxi_twi_resources[i * SUNXI_TWI_RES_NUM].start = SUNXI_TWI_MEM_START(i);1392 sunxi_twi_resources[i * SUNXI_TWI_RES_NUM].end = SUNXI_TWI_MEM_END(i);1393 sunxi_twi_resources[i * SUNXI_TWI_RES_NUM].flags = IORESOURCE_MEM; ... 1398 //准备平台设备所用的平台数据1399 sunxi_twi_pdata[i].bus_num = i;1400 sunxi_twi_pdata[i].frequency = SUNXI_TWI_SPEED(i); //i2c传输的标准速率100Kbsp, 高速400Kbsp. 这里的值是200Kbsp.1401 //初始化平台设备1402 sunxi_twi_device[i].name = SUNXI_TWI_DEV_NAME; // "twi"1403 sunxi_twi_device[i].id = i;1404 sunxi_twi_device[i].resource = &sunxi_twi_resources[i * SUNXI_TWI_RES_NUM];1405 sunxi_twi_device[i].num_resources = SUNXI_TWI_RES_NUM;1406 sunxi_twi_device[i].dev.platform_data = &sunxi_twi_pdata[i];1407 sunxi_twi_device[i].dev.release = sunxi_i2c_release;1408 }
///////////////////////////////////////////////////////////////
1368 static struct platform_driver sunxi_i2c_driver = { //控制器的平台驱动1369 .probe = sunxi_i2c_probe,1370 .remove = __devexit_p(sunxi_i2c_remove),1371 .driver = {1372 .name = SUNXI_TWI_DEV_NAME, // "twi",与平台设备是按名字匹配1373 .owner = THIS_MODULE,1374 .pm = SUNXI_I2C_DEV_PM_OPS,1375 },1376 };/////////// 在linux内核里,i2c控制器驱动好后用struct i2c_adapter的一个对象来描述."include/linux/i2c.h"struct i2c_adapter { struct module *owner; const struct i2c_algorithm *algo; //传输的协议,内核里已经实现好 void *algo_data; ... int timeout; /* in jiffies */ int retries; // i2c协议要求发出8位数据后,应由接收方回个应答。如没有收到应答,重新尝试的次数. struct device dev; //i2c_adapter也是基于device结构体来扩展的. 所以每个i2c_adapter的对象也可以在/sys目录下有相应的子目录 int nr; //控制器的序号,一般由控制器的平台设备的id指定 ...};//基本上每个芯片厂家都会在i2c_adapter基础上扩展出一个自己封装的类型. 控制器的驱动是芯片厂商负责的,所以不用过多关注 67 struct sunxi_i2c { 68 int bus_num; 69 unsigned int status; /* start, running, idle */ 70 unsigned int suspended:1; 71 struct i2c_adapter adap; //基于它扩展,内核里会管理adap成员的地址。只要得到此成员的地址,即可得出sunxi_i2c结构体对象的首地址 72 ... 92 };1154 static int __devinit sunxi_i2c_probe(struct platform_device *pdev)1155 {1156 struct sunxi_i2c *i2c = NULL;1157 struct resource *res = NULL;1158 struct sunxi_i2c_platform_data *pdata = NULL;1159 int ret, irq;1160 1161 pdata = pdev->dev.platform_data;1166 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1167 irq = platform_get_irq(pdev, 0); ...1172 if (!request_mem_region(res->start, resource_size(res), res->name)) {1173 return -ENOMEM;1174 }1175 1176 i2c = kzalloc(sizeof(struct sunxi_i2c), GFP_KERNEL); ... //i2c_adapter对象的初始化1182 i2c->adap.owner = THIS_MODULE;1183 i2c->adap.nr = pdata->bus_num; //1184 i2c->adap.retries = 3;1185 i2c->adap.timeout = 5*HZ;1186 i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;1187 i2c->bus_freq = pdata->frequency;1188 i2c->irq = irq;1189 i2c->bus_num = pdata->bus_num;1190 i2c->status = I2C_XFER_IDLE;1191 i2c->suspended = 0; ...1212 1213 i2c->adap.algo = &sunxi_i2c_algorithm; //传输的具体实现方法由芯片厂商实现。1221 i2c->adap.dev.parent = &pdev->dev;1222 1223 if (sunxi_i2c_hw_init(i2c, pdata)) {1224 ret = -EIO;1225 goto ehwinit;1226 }1227 1228 ret = i2c_add_numbered_adapter(&i2c->adap); //里面就是调用i2c_register_adapter(&i2c->adap)注册i2c控制器对象1229 if (ret < 0) {1230 I2C_ERR( "[i2c%d] failed to add adapter\n", i2c->bus_num);1231 goto eadapt;1232 }1233 static int i2c_register_adapter(struct i2c_adapter *adap) //注册i2c_adapter对象时触发{ int res = 0; ... /* Set default timeout to 1 second if not already set */ if (adap->timeout == 0) adap->timeout = HZ; dev_set_name(&adap->dev, "i2c-%d", adap->nr); adap->dev.bus = &i2c_bus_type; // i2c_adapter对象的device成员挂载到名为"i2c"的总线下, 所以在"/sys/bus/i2c/"目录下会有i2c_adapter对象的子目录, 目录名为"i2c-%d" adap->dev.type = &i2c_adapter_type; res = device_register(&adap->dev); ... if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); /* Notify drivers */ mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); mutex_unlock(&core_lock);
阅读全文
0 0
- 54 OrangePi linux内核里的i2c控制器驱动
- 61 OrangePi Linux内核里的spi控制器驱动
- 55 linux内核里基于GPIO口的I2C控制器驱动
- 17 H5里的i2c控制器驱动
- Linux内核里写i2c client 驱动的两种方式
- Linux i2c子系统(四) _从i2c-s3c24xx.c看i2c控制器驱动的编写
- 62 linux内核里基于GPIO口的SPI控制器驱动
- Linux内核I2C子系统驱动
- Linux内核I2C子系统驱动
- 14 orangepi 内核里控制IO口
- tcc893x基于Linux内核的I2C总结(I2C基础、I2C适配器驱动分析)
- 56 linux内核里声明I2C设备的方法
- 内核下的I2C驱动
- 57 linux内核的i2c设备驱动模型
- linux驱动的i2c驱动
- 12 orangepi Linux设备驱动前言
- linux内核的I2C子系统详解1——I2C总线概览、驱动框架概览
- Linux内核I2C子系统驱动(一)
- HX711 24位A/D模块计算公式
- 单元测试类工具下载
- nginx 出现413 Request Entity Too Large问题的解决方法
- 强类型 弱类型 静态类型 动态类型
- 优化算法——截断梯度法(TG)
- 54 OrangePi linux内核里的i2c控制器驱动
- mysql查询当天整点时间,昨天整点时间
- Firebreath基础教程之四:基本编程
- redis有序集合操作 增删查
- jq div拖动(移动端和pc端)
- 6.29 CodeForce 818 A/B解题报告
- 优化算法——坐标上升法
- 揭秘悠百佳休闲食品加盟大型骗局
- linux下svnserve安装和简单配置