3、驱动源码分析

IPNC_RDK_V3.8.0.1/Source/ti_tools/ipnc_psp_arago/kernel/sound/soc/codecs/tlv320aic3x.c

3.1 注册模块

module_init(aic3x_modinit);

3.2 在初始化函数中添加i2c驱动

static int __init aic3x_modinit(void)

{

intret = 0;

#if defined(CONFIG_I2C) ||defined(CONFIG_I2C_MODULE)

ret= i2c_add_driver(&aic3x_i2c_driver);

if(ret != 0) {

printk(KERN_ERR "Failed to registerTLV320AIC3x I2C driver: %d\n",

ret);

}

#endif

returnret;

}

3.3 【驱动】

static struct i2c_driver aic3x_i2c_driver = {

.driver= {

.name = "tlv320aic3x-codec",

.owner = THIS_MODULE,

},

.probe     = aic3x_i2c_probe,

.remove= aic3x_i2c_remove,

.id_table= aic3x_i2c_id,

};

3.4 probe

static int aic3x_i2c_probe(structi2c_client *i2c,

const struct i2c_device_id *id)

{

structaic3x_pdata *pdata = i2c->dev.platform_data;

structaic3x_priv *aic3x;

intret;

conststruct i2c_device_id *tbl;

aic3x= kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);

if(aic3x == NULL) {

dev_err(&i2c->dev, "failed tocreate private data\n");

return -ENOMEM;

}

aic3x->control_data= i2c;

aic3x->control_type= SND_SOC_I2C;

i2c_set_clientdata(i2c, aic3x);

if(pdata) {

aic3x->gpio_reset =pdata->gpio_reset;

aic3x->setup = pdata->setup;

}else {

aic3x->gpio_reset = -1;

}

for(tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {

if (!strcmp(tbl->name, id->name))

break;

}

aic3x->model= tbl - aic3x_i2c_id;

ret= snd_soc_register_codec(&i2c->dev,

&soc_codec_dev_aic3x,&aic3x_dai, 1);

if(ret < 0)

kfree(aic3x);

returnret;

}

3.5 remove

static int aic3x_i2c_remove(structi2c_client *client)

{

snd_soc_unregister_codec(&client->dev);

kfree(i2c_get_clientdata(client));

return0;

}

3.6 i2c_device_id

static const struct i2c_device_id aic3x_i2c_id[] = {

[AIC3X_MODEL_3X]= { "tlv320aic3x", 0 },

[AIC3X_MODEL_33]= { "tlv320aic33", 0 },

[AIC3X_MODEL_3007]= { "tlv320aic3007", 0 },

[AIC3X_MODEL_3104]= { "tlv320aic3104", 0 },

{}

};

3.7 模块注销

static void __exit aic3x_exit(void)

{

#if defined(CONFIG_I2C) ||defined(CONFIG_I2C_MODULE)

i2c_del_driver(&aic3x_i2c_driver);

#endif

}

module_exit(aic3x_exit);

3、与i2c相关的函数

Include/linux/i2c.h中

4.1 i2c_add_driver

static inline int i2c_add_driver(structi2c_driver *driver)

{

returni2c_register_driver(THIS_MODULE,driver);

}

Drivers/i2c/i2c-core.c中

4.2 i2c_del_driver

/**

*i2c_del_driver - unregister I2C driver

*@driver: the driver being unregistered

*Context: can sleep

*/

void i2c_del_driver(structi2c_driver *driver)

{

mutex_lock(&core_lock);

bus_for_each_dev(&i2c_bus_type,NULL, driver, __process_removed_driver);

mutex_unlock(&core_lock);

driver_unregister(&driver->driver);

pr_debug("i2c-core:driver [%s] unregistered\n", driver->driver.name);

}

Include/linux/i2c.h中

4.3 i2c_set_clientdata

static inline void i2c_set_clientdata(structi2c_client *dev, void *data)

{

dev_set_drvdata(&dev->dev,data);

}

4、【设备】

Arch/arm/mach-omap2/board-ti8148ipnc.c

5.1 static struct i2c_board_info __initdatati814x_i2c_boardinfo[] = {

#ifdef CONFIG_SND_SOC_TLV320AIC3X

{

I2C_BOARD_INFO("tlv320aic3104", 0x18),

.platform_data =&dm8148ipnc_aic3x_data,

},

#endif

{

I2C_BOARD_INFO("tps65911", 0x2D),

.platform_data = &tps65911_pdata,

},

};

static void __init ti814x_evm_i2c_init(void)

{

/*There are 4 instances of I2C in TI814X but currently only one

* instance is being used on the TI8148 EVM

*/

#ifndef CONFIG_TI8148_EVM_OPTIMIZED

omap_register_i2c_bus(1,100, ti814x_i2c_boardinfo,

ARRAY_SIZE(ti814x_i2c_boardinfo));

#else

omap_register_i2c_bus(1,100, ti814x_i2c_boardinfo,

ARRAY_SIZE(ti814x_i2c_boardinfo));

#endif

}

5.2 int __init omap_register_i2c_bus(int bus_id, u32clkrate,

struct i2c_board_info const *info,

unsigned len)

{

interr;

BUG_ON(bus_id< 1 || bus_id > omap_i2c_nr_ports());

if(info) {

err = i2c_register_board_info(bus_id,info, len);

if (err)

returnerr;

}

if(!i2c_pdata[bus_id - 1].clkrate)

i2c_pdata[bus_id - 1].clkrate = clkrate;

i2c_pdata[bus_id- 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;

returnomap_i2c_add_bus(bus_id);

}

【TI i2c适配器驱动】

Arch/arm/plat-omap/i2c.c中

1、static int __init omap_i2c_add_bus(intbus_id)

{

if(cpu_class_is_omap1())

return omap1_i2c_add_bus(bus_id);

else

return omap2_i2c_add_bus(bus_id);

}

Arch/arm/plat-omap/i2c.c中

2、static inline int omap2_i2c_add_bus(intbus_id)

{

intl;

structomap_hwmod *oh;

structomap_device *od;

charoh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];

structomap_i2c_bus_platform_data *pdata;

omap2_i2c_mux_pins(bus_id);

l= snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);

WARN(l>= MAX_OMAP_I2C_HWMOD_NAME_LEN,

"String buffer overflow in I2C%ddevice setup\n", bus_id);

oh= omap_hwmod_lookup(oh_name);

if(!oh) {

pr_err("Couldnot look up %s\n", oh_name);

return-EEXIST;

}

pdata= &i2c_pdata[bus_id - 1];

/*

* When waiting for completion of a i2ctransfer, we need to

* set a wake up latency constraint for theMPU. This is to

* ensure quick enough wakeup from idle, whentransfer

* completes.

* Only omap3 has support for constraints

*/

if(cpu_is_omap34xx())

pdata->set_mpu_wkup_lat =omap_pm_set_max_mpu_wakeup_lat_compat;

od= omap_device_build(name, bus_id, oh, pdata,

sizeof(structomap_i2c_bus_platform_data),

omap_i2c_latency,ARRAY_SIZE(omap_i2c_latency), 0);

WARN(IS_ERR(od),"Could not build omap_device for %s\n", name);

returnPTR_ERR(od);

}

3、omap_hwmod_lookup(oh_name) 获取之前注册到omap_hwmod_list中的“i2c1”

Arch/arm/plat-omap/omap_device.c中

4、struct omap_device *omap_device_build(constchar *pdev_name, int pdev_id,

struct omap_hwmod *oh, void *pdata,

int pdata_len,

struct omap_device_pm_latency *pm_lats,

int pm_lats_cnt, int is_early_device)

{

structomap_hwmod *ohs[] = { oh };

if(!oh)

return ERR_PTR(-EINVAL);

returnomap_device_build_ss(pdev_name,pdev_id, ohs, 1, pdata,

pdata_len, pm_lats, pm_lats_cnt,

is_early_device);

}

5、struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,

struct omap_hwmod **ohs, int oh_cnt,

void *pdata, int pdata_len,

struct omap_device_pm_latency *pm_lats,

int pm_lats_cnt, int is_early_device)

{。。。。。。

ret = omap_device_register(od);

。。。。。。}

6、int omap_device_register(structomap_device *od)

{

pr_debug("omap_device:%s: registering\n", od->pdev.name);

od->pdev.dev.parent= &omap_device_parent;

returnplatform_device_register(&od->pdev);

}

7、int platform_device_register(structplatform_device *pdev)

{

device_initialize(&pdev->dev);

returnplatform_device_add(pdev);

}

8、int platform_device_add(struct platform_device *pdev)

{。。。。。。

ret = device_add(&pdev->dev);

。。。。。。}

linux驱动:i2c驱动(二)相关推荐

  1. linux驱动--i2c驱动学习

    转至:http://blog.csdn.net/ghostyu/article/details/8094049 预备知识 在阅读本文最好先熟悉一种i2c设备的驱动程序,并且浏览一下i2c-core.c ...

  2. 【驱动】linux下I2C驱动架构全面分析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  3. linux下I2C驱动发送IO时序,I2C驱动情景分析——怎样控制I2C时序

    内核版本:linux-3.4.2 源程序:    linux-3.4.2\drivers\i2c\busses\I2c-s3c2410.c 这次要解决的问题是:如何配置soc的I2C模块,输出想要的时 ...

  4. linux powerpc i2c驱动 之 i2c设备层的注册过程

    Linux下i2c驱动的加载过程,分为i2c设备层.i2c adapter层与i2c核心层 i2c设备驱动层也就是我们为特定i2c设备编写的驱动,下面是我自己理解的i2c驱动的注册过程 在我们写的i2 ...

  5. linux下I2C驱动架构全面分析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  6. linux下I2C驱动体系结构及在FL2440开发板上的具体实现

    最近一段时间,我在网上看了一些关于linux下i2c的文档,对i2c有了一些较浅层次了解.写这篇博客,主要是对现在已经掌握知识的巩固. Linux下I2C驱动体系结构 Linux下I2C驱动体系结构由 ...

  7. linux下I2C驱动

    linux下I2C驱动(-) by good02xaut 最近的一段时间,总结一下linux下开发I2C设备驱动的要点.内容随想,没有多加整理. I2C协议规定了主机和从机的概念,在驱动中采用的多是适 ...

  8. Linux下I2C驱动框架全面解析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  9. Zynq linux的I2C驱动学习笔记

    最近在用米尔的Z-TURN BOARD单板做小项目.顺便也加强学习I2C驱动,记一篇做记录.  I2C总线知识非常简单,SDA,SCL,他们的时序规则是:I2C总线是由数据线SDA和时钟SCL构成的串 ...

  10. linux下i2c驱动笔记

    1. 几个基本概念 1.1. 设备模型 由 总线(bus_type) + 设备(device) + 驱动(device_driver) 组成,在该模型下,所有的设备通过总线连接起来,即使有些设备没有连 ...

最新文章

  1. DOM的appendchild在IE6、7下不兼容
  2. Microsoft My Phone试用手记
  3. 注册窗口类 registerclass
  4. yytextview多种格式_iOS YYText的使用笔记一(YYTextView图文编辑器)
  5. 限流神器Sentinel,不了解一下吗?
  6. Tesla P100
  7. php携程语比,PHP 协程
  8. Android 去除最上面应用名称及图标
  9. hadoop 注解之 interfaceAudience interfaceStability
  10. 2018关于认证第三方IATF 16949:2016审核完成不符合事项分析
  11. mac上文字识别(Tesseract-OCR for mac )
  12. 【2019年5月23日】指数估值排名
  13. 工具栏的打印图标不见了_任务栏打印机图标不见 - 卡饭网
  14. netty实现http服务器
  15. python手把手教你创作趣味词云(保姆级贴心)
  16. scrapy爬虫并保存数据库
  17. 友盟新浪微博授权提示“找不到文件C8998”的解决办法
  18. springboot搭建项目环境以及整合其他技术
  19. 老男孩linux培训靠谱吗?到底该不该去?
  20. python求sinx近似值_c语言求sinx的近似值 c语言求sinx近似值

热门文章

  1. Linux那些事儿之我是Sysfs(9)sysfs文件系统模型
  2. 5.基于STM32F103+OV7670的网络摄像头
  3. 张正友相机标定代码(c++python)
  4. 【实现手机端上滑滚动加载列表】判断页面是否滚动到底部或者指定元素位置
  5. 在CentOS 6.9 x86_64的OpenResty 1.13.6.1上使用基于Redis实现动态路由示例
  6. 在CentOS 6.3 64bit上安装libunwind库
  7. 3G重选至4G--基于优先级
  8. [每日一讲] Python系列:Python概述
  9. 原 史上最简单的SpringCloud教程 | 第八篇: 消息总线(Spring Cloud Bus)(Finchley版本)
  10. python工具使用笔记