嵌入式LINUX驱动学习之15 i2c总线源码分析
一、i2c设备的注册1.1、struct i2c_board_info结构体及头文件1.2、i2c_register_board_info()函数头文件1.2.1、i2c_register_board_info()函数实现1.2.2 i2c_register_board_info的配套函数arch_initcall()
1.3 i2c_new_device() 和 i2c_get_adapter();1.3.1 i2c_new_device() 通过模块的方式添加一个i2c设备1.3.2 i2c_get_adapter() 从内核I2C总线中获取总线适配器
1.4 i2c_new_probed_device()从地址列表中查找匹配的地址二、i2c驱动软件信息2.1结构体及函数
三、i2c设备控制命令
一、i2c设备的注册
1.1、struct i2c_board_info结构体及头文件
struct i2c_board_info
{
char type
[I2C_NAME_SIZE
];
unsigned short flags
;
unsigned short addr
;
void *platform_data
;
};
#define I2C_BOARD_INFO(dev_type, dev_addr) \
.type = dev_type, .addr = (dev_addr)
struct i2c_board_info i2c_obj_info
[] = {
{
I2C_BOARD_INFO("i2c设备匹配名称“
,i2c设备物理地址
)
}
}
1.2、i2c_register_board_info()函数头文件
使用方法见: i2c代码举例(三轴加速度传感器MMA8653)方式一
int i2c_register_board_info(int busnum
, struct i2c_board_info
const *info
, unsigned n
);
1.2.1、i2c_register_board_info()函数实现
int __init
i2c_register_board_info(int busnum
,\
struct i2c_board_info
const *info
, unsigned len
)
{
int status
;
down_write(&__i2c_board_lock
);
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
);
}
up_write(&__i2c_board_lock
);
return status
;
}
1.2.2 i2c_register_board_info的配套函数arch_initcall()
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
#define arch_initcall(fn) __define_initcall("3",fn,3)
1.3 i2c_new_device() 和 i2c_get_adapter();
使用方法见: i2c代码举例(三轴加速度传感器MMA8653)方式二
1.3.1 i2c_new_device() 通过模块的方式添加一个i2c设备
struct i2c_client
* i2c_new_device(struct i2c_adapter
*adap
, struct i2c_board_info
const *info
);
1.3.2 i2c_get_adapter() 从内核I2C总线中获取总线适配器
struct i2c_adapter
*i2c_get_adapter(int nr
)
1.4 i2c_new_probed_device()从地址列表中查找匹配的地址
和i2c_new_device()二选一使用即可
extern struct i2c_client
*
i2c_new_probed_device(struct i2c_adapter
*adap
,
struct i2c_board_info
*info
,
unsigned short const *addr_list
,
int (*probe
)(struct i2c_adapter
*, unsigned short addr
));
二、i2c驱动软件信息
2.1结构体及函数
struct i2c_driver
{
int (*probe
)(struct i2c_client
*, const struct i2c_device_id
*);
int (*remove
)(struct i2c_client
*);
struct device_driver driver
;
}
int i2c_register_driver(struct module
*owner
, struct i2c_driver
*driver
);
i2c_add_driver(driver
);
void i2c_del_driver(struct i2c_driver
*driver
);
三、i2c设备控制命令
s32
i2c_smbus_read_byte(const struct i2c_client
*client
);
s32
i2c_smbus_write_byte(const struct i2c_client
*client
, u8 value
);
s32
i2c_smbus_read_byte_data(const struct i2c_client
*client
,u8 command
);
s32
i2c_smbus_write_byte_data(const struct i2c_client
*client
,u8 command
, u8 value
);
s32
i2c_smbus_read_word_data(const struct i2c_client
*client
,u8 command
);
s32
i2c_smbus_write_word_data(const struct i2c_client
*client
,u8 command
, u16 value
);
s32
i2c_smbus_read_block_data(const struct i2c_client
*client
,u8 command
, u8
*values
);
s32
i2c_smbus_write_block_data(const struct i2c_client
*client
,u8 command
, u8 length
, const u8
*values
);