linux iic驱动编程之二 向总线注册设备(2)

来源:互联网 发布:清宫表和49算法哪个准 编辑:程序博客网 时间:2024/05/29 16:45
前言:本人是接触linux驱动开发的初学者,如有什么错误,希望您能够指出来,万分感谢,希望大家一起学习,一起进步!!

linux iic驱动编程之二 向总线注册iic设备 动态加载

本文主要讲解内核提供例子:注册iic设备的二总方法 显示的实例化iic设备

linux 内核教程原文如下

This method is appropriate when a larger device uses an I2C bus for
internal communication. A typical case is TV adapters. These can have a
tuner, a video decoder, an audio decoder, etc. usually connected to the
main chip by the means of an I2C bus. You won't know the number of the I2C
bus in advance, so the method 1 described above can't be used. Instead,
you can instantiate your I2C devices explicitly. This is done by filling
a struct i2c_board_info and calling i2c_new_device().


当较大的设备使用I2C总线进行内部通信时,此方法是合适的。典型的例子是电视适配器。它们可以有一个调谐器、一个视频解码器、一个音频解码器等,通常通过I2C总线连接到主芯片。您不会预先知道I2C总线的数量,所以上面描述的方法1不能使用。相反,你可以实例化I2C设备明确。这是通过填充结构i2c_board_info叫i2c_new_device()做。

相关的结构体和用到的函数介绍:
struct i2c_board_info {
char type[I2C_NAME_SIZE]; // 用于初始化 iic_client.name
unsigned shortflags;                      // 用于初始化 iic_client.flags
unsigned shortaddr;                      //  用于初始化 iic_client.addr
void *platform_data;              //  用于初始化 iic_client.platform_data
struct dev_archdata*archdata;      //  用于初始化 iic_client.archdata
struct device_node *of_node;        //  用于初始化 iic_client.of_node
int irq;                                  //  用于初始化 iic_client.irq
};

 I2C_BOARD_INFO(dev_type, dev_addr) iic设备名字和地址

struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
adap:iic适配器,在linux的iic子系统下,一个iic适配器相当于一个就代表一条iic总线,而挂接到iic总线上的设备通用             iic_clinet结构体来表示。

i2c_adapter结构体相关的函数:
extern int i2c_add_adapter(struct i2c_adapter *);     //向内核注册一个iic适配器
extern int i2c_del_adapter(struct i2c_adapter *);      //注销一个iic适配器
extern struct i2c_adapter *i2c_get_adapter(int nr);  // 获取一个适配器
extern void i2c_put_adapter(struct i2c_adapter *adap); //释放这个适配器

用iic_new_device 函数来注册设备的方法如下 这个函数是假设iic设备已经存在的情况之下
#include <linux/kernel.h> 
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>

static struct i2c_board_info at24cxx_info = {
I2C_BOARD_INFO("at24c08", 0x50),
};

static struct i2c_client *at24cxx_client;


static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap;


i2c_adap = i2c_get_adapter(0);
at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info);
i2c_put_adapter(i2c_adap);

return 0;
}


static void at24cxx_dev_exit(void)
{
i2c_unregister_device(at24cxx_client);
}

module_init(at24cxx_dev_init);
module_exit(at24cxx_dev_exit);
MODULE_LICENSE("GPL");

用函数 i2c_new_probed_device来注册的实例 用设备实际存在才能注册成功
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>


static struct i2c_client *at24cxx_client;


static const unsigned short addr_list[] = { 0x60, 0x50, I2C_CLIENT_END };


static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap;
struct i2c_board_info at24cxx_info;


memset(&at24cxx_info, 0, sizeof(struct i2c_board_info));
strlcpy(at24cxx_info.type, "at24c08", I2C_NAME_SIZE);


i2c_adap = i2c_get_adapter(0);
at24cxx_client = i2c_new_probed_device(i2c_adap, &at24cxx_info, addr_list, NULL);
i2c_put_adapter(i2c_adap);


if (at24cxx_client)
return 0;
else
return -ENODEV;
}


static void at24cxx_dev_exit(void)
{
i2c_unregister_device(at24cxx_client);
}




module_init(at24cxx_dev_init);
module_exit(at24cxx_dev_exit);
MODULE_LICENSE("GPL");