关闭

I2C设备驱动流程

560人阅读 评论(0) 收藏 举报
分类: Kernel Device Driver2010-09-24 20:07 788人阅读 评论(0) 收藏 举报

一、I2C设备驱动流程

1) i2c_register_board_info定义I2C器件信息(NameAddressetc.

static struct i2c_board_info __initdata pi2c_board_info[] = {

       {

              I2C_BOARD_INFO("max1586", 0x14),

              .platform_data = &max1587a_info,

       },

};

 

i2c_register_board_info(1, ARRAY_AND_SIZE(pi2c_board_info));

/* 1表示该I2C设备挂在I2C-1 ,注册I2C adapt时相应的id = 1 */

 

/* i2c */

static struct i2c_gpio_platform_data i2c_bus_data = {

       .sda_pin = VIPER_RTC_I2C_SDA_GPIO,

       .scl_pin = VIPER_RTC_I2C_SCL_GPIO,

       .udelay  = 10,

       .timeout = HZ,

};

 

static struct platform_device i2c_bus_device = {

       .name          = "i2c-gpio",

       .id         = 1,   /* /sys/class/i2c-adapt/i2c-1  */

       .dev = {

              .platform_data = &i2c_bus_data,

       }

};

 

将I2C器件信息注册到I2C的器件列表中:

struct i2c_devinfo {

       struct list_head list;                   /* 双向链表   */

       int                busnum;

       struct i2c_board_info     board_info;     /* i2c器件信息 */

};

 

int __init

i2c_register_board_info(int busnum,

       struct i2c_board_info const *info, unsigned len)

{

       int status;

       down_write(&__i2c_board_lock);

 

       /* dynamic bus numbers will be assigned after the last static one */

       if (busnum >= __i2c_first_dynamic_bus_num)

              __i2c_first_dynamic_bus_num = busnum + 1;

       for (status = 0; len; len--, info++) {

              struct i2c_devinfo   *devinfo;

              devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);

              if (!devinfo) {

                     pr_debug("i2c-core: can't register boardinfo!/n");

                     status = -ENOMEM;

                     break;

              }

 

              devinfo->busnum = busnum;

              devinfo->board_info = *info;

              list_add_tail(&devinfo->list, &__i2c_board_list);

              /* 加入__i2c_board_list 链表中 */

       }

       up_write(&__i2c_board_lock);

       return status;

}

 

2) 注册I2C device

i2c_register_adapter -> i2c_scan_static_board_info -> i2c_new_device

struct i2c_client *

i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)

{

       struct i2c_client       *client;

       int                status;

       client = kzalloc(sizeof *client, GFP_KERNEL);

       if (!client)

              return NULL;

       client->adapter = adap;

       client->dev.platform_data = info->platform_data;

       if (info->archdata)

              client->dev.archdata = *info->archdata;

 

       client->flags = info->flags;

       client->addr = info->addr;   /* 取得I2C器件地址 */

       client->irq = info->irq;

       strlcpy(client->name, info->type, sizeof(client->name));

 

       /* Check for address validity */

       status = i2c_check_client_addr_validity(client);

       if (status) {

              dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx/n",

                     client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);

              goto out_err_silent;

       }

       /* Check for address business */

       status = i2c_check_addr_busy(adap, client->addr);

       if (status)

              goto out_err;

       client->dev.parent = &client->adapter->dev;

       client->dev.bus = &i2c_bus_type;

       client->dev.type = &i2c_client_type;

 

       dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),

                   client->addr);

       status = device_register(&client->dev);   /* 注册器件 */

       if (status)

              goto out_err;

    …

}

 

3) I2C读写

static inline int pm860x_read_device(struct i2c_client *i2c,

                                 int reg, int bytes, void *dest)

{

       unsigned char data;

       int ret;

       data = (unsigned char)reg;

       ret = i2c_master_send(i2c, &data, 1);  /* 写地址 */

       if (ret < 0)

              return ret;

       ret = i2c_master_recv(i2c, dest, bytes);  /* 读数据 */

       if (ret < 0)

              return ret;

       return 0;

}

 

static inline int pm860x_write_device(struct i2c_client *i2c,

                                  int reg, int bytes, void *src)

{

       unsigned char buf[bytes + 1];

       int ret;

       buf[0] = (unsigned char)reg;

       memcpy(&buf[1], src, bytes);

       ret = i2c_master_send(i2c, buf, bytes + 1);  /* 写地址&数据 */

       if (ret < 0)

              return ret;

       return 0;

}

 

/* i2c-core.c 函数 */

int i2c_master_send(struct i2c_client *client, const char *buf, int count)

{

       int ret;

       struct i2c_adapter *adap = client->adapter;

       struct i2c_msg msg;

       msg.addr = client->addr;  /*  I2C器件地址 */

       msg.flags = client->flags & I2C_M_TEN;

       msg.len = count;

       msg.buf = (char *)buf;

       ret = i2c_transfer(adap, &msg, 1);

 

       /* If everything went ok (i.e. 1 msg transmitted), return #bytes

          transmitted, else error code. */

       return (ret == 1) ? count : ret;

}

 

int i2c_master_recv(struct i2c_client *client, char *buf, int count)

{

       struct i2c_adapter *adap = client->adapter;

       struct i2c_msg msg;

       int ret;

       msg.addr = client->addr;

       msg.flags = client->flags & I2C_M_TEN;

       msg.flags |= I2C_M_RD;

       msg.len = count;

       msg.buf = buf;

       ret = i2c_transfer(adap, &msg, 1);

 

       /* If everything went ok (i.e. 1 msg transmitted), return #bytes

          transmitted, else error code. */

       return (ret == 1) ? count : ret;

}

 

 

 

 

二、I2C时序

1)  START/STOP时序

 

 

2)  I2C器件地址结构(bit7~Bit1)

 

 

FIXME:”1” Read, “0” Write

3) 字节写

START + ( Device address +W ) + (Register Address) + (Data) + STOP

 

4) 多字节写

 

5) *读操作

 

START + (Device Address + w) + (Register Address) +RESTART + (Device Address + R) +(Data) +STOP

分享到: 
0
0
查看评论

Linux系统I2C设备驱动编写方法

硬件平台:飞思卡尔IMX6 内核版本:kernel3.0.35 Linux的I2C子系统分为三层,I2C核心层,I2C总线驱动层和I2C设备驱动层。I2C核心层由内核开发者提供,I2C总线驱动层有芯片厂商提供,而I2C设备驱动层由于设备的差异性,就只能是具体的开发需求具体实现了。而本实例...
  • BorntoX
  • BorntoX
  • 2016-07-11 08:56
  • 2054

两种方式的i2c设备驱动的编写方法

我的理念:简单实用即可,不要搞一堆源码出来,结果让人看了以后还不知道怎么用,看我的: 1、在arch/arm/mach-xxx/ 自己的平台文件里添加i2c信息,美其名曰:i2c_board_info 例如: static struct i2c_board_info _...
  • yyyyyyyyyywwwwwwwwww
  • yyyyyyyyyywwwwwwwwww
  • 2015-12-18 10:57
  • 711

Linux I2C设备驱动编写(一)

在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I2C driver 某个I2C设备的设备驱动,可以以driver理解。 I2C client 某个I2C设备的设备声明,可以以device理解。 I2C adapter 是CPU集成或外接的I2C适配...
  • airk000
  • airk000
  • 2014-03-16 23:24
  • 33682

Linux3.5下I2C设备驱动程序

一、驱动框架       以4412+linux3.5平台为例,说明Linux下I2C设备驱动程序。这里先介绍框架的原因在于如果一条I2C总线上只连接一个I2C设备,比如本文将要用到的示例EEPROM,那么只需要以字符型设备驱动框架来写此驱动即可...
  • fengel_cs
  • fengel_cs
  • 2016-01-15 11:54
  • 1355

【linux kernel 3.18】I2C总线驱动注册、注销和使用流程

【linux kernel 3.18】I2C总线驱动注册、注销和使用流程 一、前言 前言主要阐述了编写该技术文档的目的,使用的平台环境,以及看懂该文档所需要掌握的基本知识,方便学习者按图索骥,填充相关的知识体系。 在linux驱动开发的过程中,我们每天会接触到大量的代码,会遇到不同的总线和设备,有时...
  • Lcloud671
  • Lcloud671
  • 2016-09-13 00:48
  • 337

Linux设备驱动篇——[I2C设备驱动-1]

Linux 设备驱动篇之I2c设备驱动 fulinux 一、I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设备驱动、I2C总线驱动和I2C核心。 1.I2C核心 I2C核...
  • luoyouren
  • luoyouren
  • 2015-04-24 12:13
  • 1129

编写i2c驱动-基于Linux3.10

很多芯片的控制方法均使用了i2c的方式,EEPROM,音频芯片AK4951,索尼、松下、豪威的图像传感器、电机驱动等均采用i2c的控制方式。彻底的弄懂i2c设备驱动,对于理解其它驱动非常有帮助,从投入和产出比而言还是值得的。 I2c设备分为两种,一种叫i2c适配器(adpater),一种客户端(c...
  • shichaog
  • shichaog
  • 2014-11-16 08:52
  • 1931

i2c设备驱动的四种构造方法

i2c设备驱动属于字符设备驱动,其构造自然是跟字符设备的结构一样了,字符设备:1、 分配字符设备号(主次设备号),设置为0,表示自动分配设备号  2、构造file_operatios 3、注册设备,register_chrdev(1,2,3),三个参数分别是设备号,名称(不重要,随便起)...
  • wangweiqiang1325
  • wangweiqiang1325
  • 2016-09-23 16:33
  • 603

新路程------hi3516a标准简单版i2c设备驱动

设备驱动如下: #include #include #include #include #include #include #include #include #include #include //#include #include #includ...
  • u013308744
  • u013308744
  • 2017-08-10 11:59
  • 247

I2C设备驱动流程

I2C设备驱动流程 一、I2C设备驱动流程 1) i2c_register_board_info定义I2C器件信息(Name,Address,etc.) static struct i2c_board_info __initdata pi2c_board_info[] = {  &...
  • Frank_zhangjian
  • Frank_zhangjian
  • 2013-11-20 16:48
  • 619
    个人资料
    • 访问:540546次
    • 积分:9366
    • 等级:
    • 排名:第2326名
    • 原创:215篇
    • 转载:308篇
    • 译文:10篇
    • 评论:45条
    My Github
    最新评论