zoukankan      html  css  js  c++  java
  • I2C设备驱动流程

    分类: 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

    分享到: 
  • 上一篇:vmalloc中物理地址重映射函数分析
  • 下一篇:驱动中id_table的分析(Input/I2C)
查看全文
  • 相关阅读:
    普通的一个python脚本,hadoop进军的准备
    Python之数据类型讲解
    开始博客的理由
    【微机原理及应用】程序的分类
    【jvm】jvm学习第二篇。jvm运行机制
    【jvm】jvm学习第一篇。初识jvm
    【it公司】it公司简介-项目流程-研发小技巧
    【感悟】20岁的人生不应该停止奋斗。----------------努力努力再努力
    【书籍学习】史上最全的Java进阶书籍推荐
    【职业规划】3年工作经验的程序员应该具备的技能
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124218.html
  • Copyright © 2011-2022 走看看