源码位于: driver/hwmon/mma7660.c
参考博客:http://www.cnblogs.com/pengdonglin137/p/5240416.html
参考博客:http://blog.youkuaiyun.com/rockrockwu/article/details/7434953 i2c子系统之i2c bus初始化——i2c_init()
在Linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init()函数。
参考博客:http://www.cnblogs.com/pengdonglin137/p/5240416.html
参考mma7660的芯片数据手册:https://wenku.baidu.com/view/3ef59c28ed630b1c59eeb521.html
那么驱动分析完了,设备板级配置文件配置在哪里呢?
代码位置:/arch/arm/mach-exynos/mach-tiny4412.c
在大约2856行的地方,可以看到:
这里通过CONFIG_SENSORS_MMA7660来识别是否有在内核中配置这个sensor,这个配置在源码根目录下的tiny4412_android_defconfig中:
可以搜索到:CONFIG_SENSORS_MMA7660=y
//判断是否有配置CONFIG_SENSORS_MMA7660
#ifdef CONFIG_SENSORS_MMA7660
//如果配置了,就包含7660驱动相关的头文件,并配置板级信息
#include <linux/mma7660.h>
static struct mma7660_platform_data mma7660_pdata = {
.irq = IRQ_EINT(25), //设置外部中断号
.poll_interval = 100,
.input_fuzz = 4,
.input_flat = 4,
};
#endif
static struct s3c2410_platform_i2c tiny4412_i2c3_data __initdata = {
.flags = 0,
.bus_num = 3,
.slave_addr = 0x10,
.frequency = 200*1000,
.sda_delay = 100,
};
static struct i2c_board_info i2c_devs3[] __initdata = {
#ifdef CONFIG_SENSORS_MMA7660
{
//这就是所谓的i2c_client的信息,在驱动中可以获取
I2C_BOARD_INFO("mma7660", 0x4c), //I2C板级注册信息
.platform_data = &mma7660_pdata, //将信息存储在platform_data中:
},
#endif
};
以下为I2C_BOARD_INFO的原型:
/**
* I2C_BOARD_INFO - macro used to list an i2c device and its address
* @dev_type: identifies the device type
* @dev_addr: the device's address on the bus.
*
* This macro initializes essential fields of a struct i2c_board_info,
* declaring what has been provided on a particular board. Optional
* fields (such as associated irq, or device-specific platform_data)
* are provided using conventional syntax.
*/
#define I2C_BOARD_INFO(dev_type, dev_addr) \
.type = dev_type, .addr = (dev_addr)
大约4084行,找到初始化函数:
static void __init smdk4x12_machine_init(void)
大约4147行可以看到,在初始化硬件信息的时候向i2c注册了板级信息:
s3c_i2c3_set_platdata(&tiny4412_i2c3_data);
i2c_register_board_info(3, i2c_devs3, ARRAY_SIZE(i2c_devs3));
该函数原型:
int __init
i2c_register_board_info(int busnum,
struct i2c_board_info const *info, unsigned len)
i2c_board_info结构体的实现:
struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;
int irq;
};
而i2c_client的数据存放在以下结构体中;
//#define I2C_NAME_SIZE 20
struct i2c_client {
unsigned short flags; //标明i2c设备的地址占多少位, 0为7bit, I2C_CLIENT_TEN为10位
unsigned short addr; //设备地址
char name[I2C_NAME_SIZE]; //设备名称
struct i2c_adapter *adapter; //指向使用的i2c控制器
struct i2c_driver *driver; //指向匹配上的i2c设备驱动
struct device dev; //描述设备的结构体
int irq; //设备的中断号
struct list_head detected; //可以将这些信息加入到链表中去
};
适配器相关的结构体:
//描述一个i2c控制器
struct i2c_adapter {
struct module *owner;
unsigned int id;
unsigned int class; /* classes to allow probing for */
const struct i2c_algorithm *algo; //使用哪种协议去传输数据
void *algo_data;
char name[48];
struct completion dev_released;
...
};
参考博客:http://blog.youkuaiyun.com/rockrockwu/article/details/7434752 i2c子系统之内核中I2C子系统的结构参考博客:http://blog.youkuaiyun.com/rockrockwu/article/details/7434953 i2c子系统之i2c bus初始化——i2c_init()
在Linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init()函数。
最后再说说,驱动和设备是怎么联系起来的: