http://blog.csdn.net/liuyangxiyou/article/details/6299184
i2c subsystem的故事还要从很久以前说起,那是一个混沌初开的年代......
1、板子初始化
arch/arm/mach-msm/board-msm7x30.c
static void __init msm7x30_init(void)
{
......
(1) platform_add_devices(devices, ARRAY_SIZE(devices));
......
(2) msm_device_i2c_init();
msm_device_i2c_2_init();
......
(3) i2c_register_board_info(4 /* QUP ID */, msm_camera_boardinfo,
ARRAY_SIZE(msm_camera_boardinfo));
......
}
(1) 在此处注册了很多的platform_device devices[],在这一堆的platform_devices中有
msm_device_i2c,
msm_device_i2c_2,
这样两个设备(具体的区别还没有弄清楚,有可能是该板子有两条i2c总线),它们其实就是很容易被人们遗忘的i2c controler,它们被当作platform_device在板子初始化时进行注册。
platform_device的注册过程不详细讲述了,只讲一下最重要的两部match和probe:
a、match
drivers/base/base.h
120 static inline int driver_match_device(struct device_driver *drv,
121 struct device *dev)
122 {
)>123 return drv->bus->match ? drv->bus->match(dev, drv) : 1;
124 }
call bus->match
671 static int platform_match(struct device *dev, struct device_driver *drv)
672 {
673 struct platform_device *pdev = to_platform_device(dev);
674 struct platform_driver *pdrv = to_platform_driver(drv);
675
676 /* match against the id table first */
677 if (pdrv->id_table)
678 return platform_match_id(pdrv->id_table, pdev) != NULL;
679
680 /* fall-back to driver name match */
681 return (strcmp(pdev->name, drv->name) == 0);
682 }
首先看platform_driver有没有定义id_table,有的话:
644 static const struct platform_device_id *platform_match_id(
645 const struct platform_device_id *id,
646 struct platform_device *pdev)
647 {
648 while (id->name[0]) {
649 if (strcmp(pdev->name, id->name) == 0) { platform_driver有可能支持多个platform_device,所以可能会有多个platform_device_id项
650 pdev->id_entry = id;
651 return id;
652 }
653 id++;
654 }
655 return NULL;
656 }
比较platform_device->name和platform_driver->id_entry->name,否则
platform_device->name和device_driver->name
b、probe
static int really_probe(struct device *dev, struct device_driver *drv)
120 if (dev->bus->probe) {
121 ret = dev->bus->probe(dev);
122 if (ret)
123 goto probe_failed;
124 } else if (drv->probe) {
125 ret = drv->probe(dev);
126 if (ret)
127 goto probe_failed;
128 }
这里先看能不能call bus->probe,不能则call devices_driver->probe
483 int platform_driver_register(struct platform_driver *drv)
484 {
485 drv->driver.bus = &platform_bus_type;
486 if (drv->probe)
'> 487 drv->driver.probe = platform_drv_probe;
488 if (drv->remove)
489 drv->driver.remove = platform_drv_remove;
490 if (drv->shutdown)
491 drv->driver.shutdown = platform_drv_shutdown;
}> 492
493 return driver_register(&drv->driver);
494 }
486和487
先看有没有platform_driver->probe,有就对device_driver->probe赋值platform_drv_probe,在上面调用devices_driver->probe实际就是调用platform_drv_probe,而platform_drv_probe又会调用platform_driver->probe,这个probe是用户写的具体设备驱动的probe。但是在此时还不会去调用driver的probe,因为现在还没有platform_driver模块被加载,
板子初始化函数继续执行。
(2)msm_device_i2c_init();
static void __init msm_device_i2c_init(void)
{
if (msm_gpios_request(msm_i2c_gpios_hw, ARRAY_SIZE(msm_i2c_gpios_hw)))
pr_err("failed to request I2C gpios/n");
msm_device_i2c.dev.platform_data = &msm_i2c_pdata;
}
主要是gpio的申请和i2c controler 平台数据的赋值。
(3)i2c_register_board_info(4 /* QUP ID */, msm_camera_boardinfo,
ARRAY_SIZE(msm_camera_boardinfo));
这个函数主要是把i2c 的外围设备信息结构体struct ic2_board_info 分装进struct i2c_devinfo结构,再把这个结构放到__i2c_board_list这个链表上。
该函数的第一个参数其实是该i2c 设备所属的adapter的编号,不同的adapter使用的低层i2c通信协议算法可能不一样。
2、i2c controler driver 的加载过程
drivers/i2c/busses/i2c-msm.c 该文件就是i2c controler的驱动程序。
780 static struct platform_driver msm_i2c_driver = {
781 .probe = msm_i2c_probe,
782 .remove = msm_i2c_remove,
783 .suspend = msm_i2c_suspend,
784 .resume = msm_i2c_resume,
785 .driver = {
786 .name = "msm_i2c",
787 .owner = THIS_MODULE,
788 },
789 };
}>790
791 /* I2C may be needed to bring up other drivers */
792 static int __init
793 msm_i2c_init_driver(void)
794 {
795 return platform_driver_register(&msm_i2c_driver);
796 }
platform_driver_register(&msm_i2c_driver) 的过程和platform_device_register的过程很相似,主要两部还是match和probe,不过这回platform_bus_type上已经有设备了,它回去probe设备,并最终调用platform_driver的probe函数msm_i2c_probe。我们来看一看该函数做了些什么。
static int
msm_i2c_probe(struct platform_device *pdev)
{
......
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?/n");
return -ENODEV;
}
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?/n");
return -ENODEV;
}
ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "I2C region already claimed/n");
return -EBUSY;
}
clk = clk_get(&pdev->dev, "i2c_clk");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Could not get clock/n");
ret = PTR_ERR(clk);
goto err_clk_get_failed;
}
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "platform data not initialized/n");
ret = -ENOSYS;
goto err_clk_get_failed;
}
if (!pdata->msm_i2c_config_gpio) {
dev_err(&pdev->dev, "config_gpio function not initialized/n");
ret = -ENOSYS;
goto err_clk_get_failed;
}
/* We support frequencies upto FAST Mode(400KHz) */
if (pdata->clk_freq <= 0 || pdata->clk_freq > 400000) {
dev_err(&pdev->dev, "clock frequency not supported/n");
ret = -EIO;
goto err_clk_get_failed;
}
以上的代码不用说了,就是在获取配置i2c controler的资源。
分配了一个struct msm_i2c_dev的i2c controler的结构体,里面都是i2c controler的资源,以方便以后使用
dev = kzalloc(sizeof(struct msm_i2c_dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err_alloc_dev_failed;
}
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->clk = clk;
dev->pdata = pdata;
dev->base = ioremap(mem->start, (mem->end - mem->start) + 1);
if (!dev->base) {
ret = -ENOMEM;
goto err_ioremap_failed;
}
dev->one_bit_t = USEC_PER_SEC/pdata->clk_freq;
spin_lock_init(&dev->lock);
platform_set_drvdata(pdev, dev); //pdev->dev->p->driver_data = dev(struct msm_i2c_dev)
clk_enable(clk);
if (pdata->rmutex) {
struct remote_mutex_id rmid;
rmid.r_spinlock_id = pdata->rsl_id;
rmid.delay_us = 10000000/pdata->clk_freq;
if (remote_mutex_init(&dev->r_lock, &rmid) != 0)
pdata->rmutex = 0;
}
/* I2C_HS_CLK = I2C_CLK/(3*(HS_DIVIDER_VALUE+1) */
/* I2C_FS_CLK = I2C_CLK/(2*(FS_DIVIDER_VALUE+3) */
/* FS_DIVIDER_VALUE = ((I2C_CLK / I2C_FS_CLK) / 2) - 3 */
i2c_clk = 19200000; /* input clock */
fs_div = ((i2c_clk / pdata->clk_freq) / 2) - 3;
hs_div = 3;
clk_ctl = ((hs_div & 0x7) << 8) | (fs_div & 0xff);
writel(clk_ctl, dev->base + I2C_CLK_CTL);
printk(KERN_INFO "msm_i2c_probe: clk_ctl %x, %d Hz/n",
clk_ctl, i2c_clk / (2 * ((clk_ctl & 0xff) + 3)));
i2c_set_adapdata(&dev->adap_pri, dev); //dev(struct msm_i2c_dev)->adap_pri(struct i2c_adapter)->dev->p->driver_data = dev(struct msm_i2c_dev)
dev->adap_pri.algo = &msm_i2c_algo; //这个比较重要,使用来进行低层i2c通信的函数接口结构体
strlcpy(dev->adap_pri.name,
"MSM I2C adapter-PRI",
sizeof(dev->adap_pri.name));
dev->adap_pri.nr = pdev->id; //platform_device的 id 就成了i2c_adapter的编号
ret = i2c_add_numbered_adapter(&dev->adap_pri); //先不讲,后面再说
if (ret) {
dev_err(&pdev->dev, "Primary i2c_add_adapter failed/n");
goto err_i2c_add_adapter_failed;
}
i2c_set_adapdata(&dev->adap_aux, dev); //struct msm_i2c_dev 中有两个struct i2c_adapter,初始化另一个
dev->adap_aux.algo = &msm_i2c_algo;
strlcpy(dev->adap_aux.name,
"MSM I2C adapter-AUX",
sizeof(dev->adap_aux.name));
dev->adap_aux.nr = pdev->id + 1; //adapter 的编号不一样
ret = i2c_add_numbered_adapter(&dev->adap_aux);
if (ret) {
dev_err(&pdev->dev, "auxiliary i2c_add_adapter failed/n");
i2c_del_adapter(&dev->adap_pri);
goto err_i2c_add_adapter_failed;
}
ret = request_irq(dev->irq, msm_i2c_interrupt, //注册中断
IRQF_TRIGGER_RISING, pdev->name, dev);
if (ret) {
dev_err(&pdev->dev, "request_irq failed/n");
goto err_request_irq_failed;
}
dev->pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY, //不知道是干啥的?
PM_QOS_DEFAULT_VALUE);
if (!dev->pm_qos_req) {
dev_err(&pdev->dev, "pm_qos_add_request failed/n");
goto err_pm_qos_add_request_failed;
}
disable_irq(dev->irq);//中断屏蔽
dev->suspended = 0;
mutex_init(&dev->mlock);
dev->clk_state = 0;
/* Config GPIOs for primary and secondary lines */ //为两条i2c总线配置gpio
pdata->msm_i2c_config_gpio(dev->adap_pri.nr, 1);
pdata->msm_i2c_config_gpio(dev->adap_aux.nr, 1);
clk_disable(dev->clk); //不知道干啥的?
setup_timer(&dev->pwr_timer, msm_i2c_pwr_timer, (unsigned long) dev);//不知道干啥的?
return 0;
......
}
好了该讲讲i2c_add_numbered_adapter(&dev->adap_pri)这个神气的函数了:
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
int id;
int status;
if (adap->nr & ~MAX_ID_MASK) //判断adapter是不是合法
return -EINVAL;
......
//上面的函数都是浮云,关键是下面的函数
if (status == 0)
status = i2c_register_adapter(adap);
return status;
}
static int i2c_register_adapter(struct i2c_adapter *adap)
{
int res = 0, dummy;
/* Can't register until after driver model init */
if (unlikely(WARN_ON(!i2c_bus_type.p))) {
res = -EAGAIN;
goto out_list;
}
rt_mutex_init(&adap->bus_lock);
INIT_LIST_HEAD(&adap->userspace_clients);
/* Set default timeout to 1 second if not already set */
if (adap->timeout == 0)
adap->timeout = HZ;
dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.bus = &i2c_bus_type; //总线类型是i2c_bus_type
adap->dev.type = &i2c_adapter_type; //设备类型是i2c_adapter_type
res = device_register(&adap->dev); //该函数的讲解在下面,看看都做了什么
if (res)
goto out_list;
dev_dbg(&adap->dev, "adapter [%s] registered/n", adap->name);
#ifdef CONFIG_I2C_COMPAT
res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
adap->dev.parent);
if (res)
dev_warn(&adap->dev,
"Failed to create compatibility class link/n");
#endif
/* create pre-declared device nodes */
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);//好了,遇到最关键的函数了,在下面讲解
/* Notify drivers */
mutex_lock(&core_lock);
dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
__process_new_adapter);//在i2c_bus_type 上寻找i2c_driver,让i2c_driver和i2c_adapter 建立联系,可惜,此时还没有i2c_driver
mutex_unlock(&core_lock);
return 0;
out_list:
mutex_lock(&core_lock);
idr_remove(&i2c_adapter_idr, adap->nr);
mutex_unlock(&core_lock);
return res;
}
int device_register(struct device *dev)
{
device_initialize(dev);
return device_add(dev);
}
device_initialize不讲了,直接device_add
int device_add(struct device *dev)
{
struct device *parent = NULL;
struct class_interface *class_intf;
int error = -EINVAL;
dev = get_device(dev); //这是让其引用计数加1
if (!dev)
goto done;
if (!dev->p) {
error = device_private_init(dev);//初始化dev->p(struct device_private)
if (error)
goto done;
}
/*
* for statically allocated devices, which should all be converted
* some day, we need to initialize the name. We prevent reading back
* the name, and force the use of dev_name()
*/
if (dev->init_name) {
dev_set_name(dev, "%s", dev->init_name);
dev->init_name = NULL;
}
if (!dev_name(dev)) {
error = -EINVAL;
goto name_error;
}
pr_debug("device: '%s': %s/n", dev_name(dev), __func__);
parent = get_device(dev->parent); //adapter的父设备节点应该是i2c controler 的那个platform_device设备
setup_parent(dev, parent);
/* use parent numa_node */
if (parent)
set_dev_node(dev, dev_to_node(parent));
/* first, register with generic layer. */
/* we require the name to be set before, and pass NULL */
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
if (error)
goto Error;
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
error = device_create_file(dev, &uevent_attr);
if (error)
goto attrError;
if (MAJOR(dev->devt)) {
error = device_create_file(dev, &devt_attr);
if (error)
goto ueventattrError;
error = device_create_sys_dev_entry(dev);
if (error)
goto devtattrError;
devtmpfs_create_node(dev);
}
error = device_add_class_symlinks(dev);
if (error)
goto SymlinkError;
error = device_add_attrs(dev);
if (error)
goto AttrsError;
error = bus_add_device(dev);//i2c_bus_type 添加该adatper 设备
if (error)
goto BusError;
error = dpm_sysfs_add(dev);
if (error)
goto DPMError;
device_pm_add(dev);
/* Notify clients of device addition. This call must come
* after dpm_sysf_add() and before kobject_uevent().
*/
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_probe_device(dev); //这个函数的愿意是探测adapter设备的driver,但是adapter本就没有driver,所以该函数就无功而反了。
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);// adapter的父设备节点应该是i2c controler 的那个platform_device设备,这个函数很有用,待会儿遇到i2c_client时会很有用。
if (dev->class) {
mutex_lock(&dev->class->p->class_mutex);
/* tie the class to the device */
klist_add_tail(&dev->knode_class,
&dev->class->p->class_devices);
/* notify any interfaces that the device is here */
list_for_each_entry(class_intf,
&dev->class->p->class_interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
mutex_unlock(&dev->class->p->class_mutex);
}
......
}
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo *devinfo;
down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&adapter->dev,
"Can't create device at 0x%02x/n",
devinfo->board_info.addr);
}
up_read(&__i2c_board_lock);
}
我们前面讲过,板子初始化时会把所有的i2c外围设备的信息结构struct i2c_board_info分装成struct i2c_devinfo结构,放到了__i2c_board_list链表中,是时候用了。先判断adapter的编号对不对,之后call 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;
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);//你这个info->addr的地址,在我的adapter所支持的client的addr冲突了嘛,也就是i2c_adapter->device->device_private->klist(klist_children)链接了i2c_client->device->device_private->knod(knode_parent),但是此时adapter中还没有加载任何的client,那么是什么时候加载的呢,往下看
if (status)
goto out_err;
client->dev.parent = &client->adapter->dev;//这一步也很关键,client->dev->parent设置成了adapter->dev
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;//设备类型是i2c_client_type, adapter是i2c_adapter_type
#ifdef CONFIG_OF
client->dev.of_node = info->of_node;
#endif
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr);
status = device_register(&client->dev);//好了,我们有碰见这个函数了,前面注册adapter的时候就用过他,好了就让我们看一看那最关键的几步吧。
......
}
int device_register(struct device *dev)
{
device_initialize(dev);略过......
return device_add(dev);
}
int device_add(struct device *dev)
{
......
parent = get_device(dev->parent);
setup_parent(dev, parent);
/* use parent numa_node */
if (parent)
set_dev_node(dev, dev_to_node(parent));//前面的注释中有也句“这一步也很关键”,找找,对了,那么此处的parent就是adapter->dev
......
error = bus_add_device(dev);//i2c_bus_type总线添加i2c_client这个设备
......
bus_probe_device(dev);//i2c_client没有对应的driver,所以无功返回
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);//好啦,就是这一句,这关键的一句,真实众里寻他千百度,漠然回首......我们以前见过!真实命运的作弄阿,以前一直不知道他的重要性,就像小时候你身边熟悉却不懂的人--父亲,长大了才知道当初他的一片苦心,汗颜!解释这句话就是把client->p->knode_parent 链接到了adapter->p->klist_children的尾部。让adapter和他所支持的client建立了联系,当然一个adapter可能会支持好几个client,关键看struct i2c_devinfo下的busnum和该adapter的编号nr等不等。
......
}
以上就是板子启动中platform_device msm_i2c和i2c controler driver的有关部分,可能你还没有完全明白,那好吧,我们就做一个大白话的总结!
1、板子启动时注册作为平台设备的i2c controler设备,之后将所有的i2c 外围设备的资源信息以i2c_devinfo{i2c_board_info}的形式放到了一个全局链表中。
2、在i2c controler driver的加载过程中, 创建struct msm_i2c_dev结构体和platform_device msm_i2c 对应,struct msm_i2c_dev中有两个i2c_adapter成员,创建他们,并且从那个全局链表中找到该adapter所支持的i2c_client,创建他们,并且让i2c_adapter 和i2c_client建立关联,以备以后查找。
现在所有的准备工作都已经就绪,只等i2c设备的driver一加载,i2c的设备就能正常工作了!!!