参考博客: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.csdn.net/rockrockwu/article/details/7434752 i2c子系统之内核中I2C子系统的结构
参考博客:http://blog.csdn.net/rockrockwu/article/details/7434953 i2c子系统之i2c bus初始化——i2c_init()
在Linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init()函数。
最后再说说,驱动和设备是怎么联系起来的: