您的位置 首页 开关

ARM-Linux s3c2440 之I2C剖析

内核版本linux-2.6.30.4I2C在Linux中是Bus下的一个子系统.它由客户驱动(clientdriver),i2c-core核心,i2c适配器驱动(adapterdriver)…

内核版别linux-2.6.30.4
I2C在Linux中是Bus下的一个子系统. 它由客户驱动(client driver),i2c-core中心,i2c适配器驱动(adapter driver) ,算法aglorithm组成。s3c2440中有两个i2c现适配器.作为platform_device设备在系统启动先时被注册和增加。下面咱们剖析i2c(设备,驱动,总线)的完结进程.
//填充设备资源
//struct resource结构体描绘了挂接在cpu总线上的设备实体资源
//.start:i2c寄存器开始地址; .end:i2c寄存器完毕地址; .flag:描绘设备实体的共性和特性标志

  1. staticstructresources3c_i2c_resource[]={
  2. [0]={//i2c-0
  3. .start=S3C_PA_IIC,
  4. .end=S3C_PA_IIC+SZ_4K-1,
  5. .flags=IORESOURCE_MEM,
  6. },
  7. [1]={//i2c-1
  8. .start=IRQ_IIC,
  9. .end=IRQ_IIC,
  10. .flags=IORESOURCE_IRQ,
  11. },
  12. };

/i2c适配器初始化时数据

  1. staticstructs3c2410_platform_i2cdefault_i2c_data0__initdata={
  2. .flags=0,
  3. .slave_addr=0x10,
  4. .frequency=100*1000,
  5. .sda_delay=100,
  6. };

//声明i2c适配器为platform_device

  1. structplatform_devices3c_device_i2c0={
  2. .name=”s3c2410-i2c”,
  3. #ifdefCONFIG_S3C_DEV_I2C1
  4. .id=0,
  5. #else
  6. .id=-1,
  7. #endif
  8. .num_resources=ARRAY_SIZE(s3c_i2c_resource),
  9. .resource=s3c_i2c_resource,
  10. };
  11. staticstructs3c2410_platform_i2cdefault_i2c_data0__initdata={
  12. .flags=0,
  13. .slave_addr=0x10,
  14. .frequency=100*1000,
  15. .sda_delay=100,
  16. };

//增加i2c适配器:

  1. staticstructplatform_device*smdk2440_devices[]__initdata={
  2. &s3c_device_i2c0,
  3. };

//增加plat_from_data

  1. void__inits3c_i2c0_set_platdata(structs3c2410_platform_i2c*pd)
  2. {
  3. structs3c2410_platform_i2c*npd;
  4. if(!pd)
  5. pd=&default_i2c_data0;
  6. npd=kmemdup(pd,sizeof(structs3c2410_platform_i2c),GFP_KERNEL);
  7. if(!npd)
  8. printk(KERN_ERR”%s:nomemoryforplatformdata\n”,__func__);
  9. elseif(!npd->cfg_gpio)
  10. npd->cfg_gpio=s3c_i2c0_cfg_gpio;//i2c引脚装备
  11. s3c_device_i2c0.dev.platform_data=npd;//挂接plat_form_data数据
  12. }

//界说好上面相关结构后,在smdk2440_machine_init()中被注册和增加成platform_device

  1. staticvoid__initsmdk2440_machine_init(void)
  2. {
  3. s3c24xx_fb_set_platdata(&smdk2440_fb_info);
  4. s3c_i2c0_set_platdata(NULL);
  5. //注册和增加platform_device
  6. platform_add_devices(smdk2440_devices,ARRAY_SIZE(smdk2440_devices));
  7. }

其间 smdk2440_machine_init在被赋值在MACHINE_START中
在start_kernel()–>setup_arch()时被调用,但值得注意的是i2c适配器并没有被初始化,由于还没有驱动!
经过下面能够知道platform_device_register()和device_register()的差异:

  1. platform_add_devices()–>platform_device_register()–>
  2. platform_device_add()–>device–>add()

platfrom_bus_init()时也将增加一个名叫platform的设备(struct device platform_bus):

  1. plat_form_bus_init()–>device_register()–>device_register()
  2. –>device–>add()

但这个设备是虚拟的,一切platform_device_add()后的设备都是在/devices/platform/下
由于一切plaform_device 的父母亲都是platform_bus,是在platform_device_add()中

  1. if(!pdev->dev.parent)
  2. pdev->dev.parent=&platform_bus;

我想这也便是platform_device_register()和device_register()差异吧
在reset_init()–>kernel_init()–>do_basic_setup()
–>driver_init()–>platform_bus_init()完结platform_bus总线的注册
可是现在i2c适配器并没有和驱动绑上,由于到系现在学校驱动还没有呈现呢(初始化)
只要做好前面一些的预备功夫,i2c适配器驱动才干初始化,这个是需求依照次序来的。
s3c2440-i2c适配器驱动的初始化在drivers/i2c/bus/i2c-s3c2410.c中完结
而且作为platform_driver注册。
//填充driver结构并完结相应probe,remove等函数

  1. staticstructplatform_drivers3c2440_i2c_driver={
  2. .probe=s3c24xx_i2c_probe,
  3. .remove=s3c24xx_i2c_remove,
  4. .suspend_late=s3c24xx_i2c_suspend_late,
  5. .resume=s3c24xx_i2c_resume,
  6. .driver={
  7. .owner=THIS_MODULE,
  8. .name=”s3c2440-i2c”,//
  9. },
  10. };

//初始化并注册platform_driver

  1. staticint__initi2c_adap_s3c_init(void)
  2. {
  3. intret;
  4. ret=platform_driver_register(&s3c2410_i2c_driver);//
  5. if(ret==0){
  6. printk(“registers3c2440_i2c_driver…..\n”);
  7. ret=platform_driver_register(&s3c2440_i2c_driver);
  8. if(ret)
  9. {
  10. printk(“registers3c2410_i2c_driver…..\n”);
  11. platform_driver_unregister(&s3c2410_i2c_driver);
  12. }
  13. }
  14. returnret;
  15. }
  16. subsys_initcall(i2c_adap_s3c_init);

这样适配器就和驱动绑定上了,进程是这样的:

  1. platform_driver_register()–>driver_register()–>bus_add_driver()–>driver_attach()
  2. __driver_attach()–>driver_probe_device()–>s3c24xx_i2c_probe()

而且在s3c24xx_i2c_probe()的时分调用

  1. i2c_add_numbered_adapter(&i2c->adap);

最终增加自己为i2c总线的适配器。这样剖析进程也就完毕了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/kaiguan/264934.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部