//*************************************************
// 下面是驱动的注册
//*************************************************
//
static struct platform_driver sep0611_i2c_driver = {
.probe = sep0611_i2c_probe,
.remove = sep0611_i2c_remove,
//.resume = sep0611_i2c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "sep0611-i2c",
},
};
truct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe; //情景,但这里只是赋值,没有调用
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver); //这是核心,产生sys文件系统的关联,运行probe函数
}
EXPORT_SYMBOL_GPL(platform_driver_register);
tatic int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->probe(dev); //这里的probe已经初始化为用户的probe函数
}
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
if ((drv->bus->probe && drv->probe) || //检测各个函数有没有准备好,也就是回调传参
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus); //检查是否已经注册,通过在kset链表中查找
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv); //如果没有,则进行注册,这个函数嵌套比较深
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
EXPORT_SYMBOL_GPL(driver_register);
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus); //在启动时,device初始化时已经初始化部分
if (!bus)
return -EINVAL;
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv); //关联设备的函数
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv);
error = driver_create_file(drv, &driver_attr_uevent);
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv);
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name);
}
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
if (error) {
/* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
__func__, drv->name);
}
}
kobject_uevent(&priv->kobj, KOBJ_ADD);
return 0;
out_unregister:
kfree(drv->p);
drv->p = NULL;
kobject_put(&priv->kobj);
out_put_bus:
bus_put(bus);
return error;
}
int driver_attach(struct device_driver *drv) //函数回调,传入函数指针__driver_attach,然后运行
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
EXPORT_SYMBOL_GPL(driver_attach);
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data); //回调函数的调用,这是核心
klist_iter_exit(&i);
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
if (!driver_match_device(drv, dev)) //这个函数调用总线的match函数,而总线为platform_bus_type,所以最终会调用platform_match
return 0;
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev); //这里才是真正的探测调用
up(&dev->sem);
if (dev->parent)
up(&dev->parent->sem);
return 0;
}
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
int driver_probe_device(struct device_driver *drv, struct device *dev) //其实probe函数真正的作用可以理解为申请资源以及将驱动和设备关联
{
int ret = 0;
if (!device_is_registered(dev))
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv); //核心
pm_runtime_put_sync(dev);
return ret;
}
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev);//如果这里platform总线以对probe函数传值,则调用,但由上platform_bus_type可知没有,其实也可以加个回调
if (ret)
goto probe_failed;
} else if (drv->probe) { //如果总线没有,则调用device_driver->probe的,由上可知,已经初始化为用户的probe函数
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
static int sep0611_i2c_probe(struct platform_device *pdev) //经过一系列的跳转 ,进入用户的probe函数
{
struct sep0611_i2c *i2c;
struct i2c_adapter *adap;
struct resource *mem, *ioarea;
int irq,ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); //本身的resoure已经在boardc.c中定义,通过pdev传过来
if(!mem){
dev_err(&pdev->dev, "no mem resource!\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq resource!\n");
return irq; /* -ENXIO */
}
ioarea = request_mem_region(mem->start, resource_size(mem), pdev->name); //芯片设计好后,各个模块有自己的物理地址,这已在board.c中给出,这是
if (!ioarea) {
dev_err(&pdev->dev, "I2C region already claimed\n");
return -EBUSY;
}
i2c = kzalloc(sizeof(struct sep0611_i2c), GFP_KERNEL);
if (!i2c) {
ret = -ENOMEM;
goto err_release_region;
}
init_completion(&i2c->cmd_complete);
mutex_init(&i2c->lock);
i2c->dev = get_device(&pdev->dev);
i2c->irq = irq;
platform_set_drvdata(pdev, i2c);
/*
i2c->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c->clk)) {
ret = -ENODEV;
goto err_free_mem;
}
clk_enable(i2c->clk);
*/
i2c->base = ioremap(mem->start, resource_size(mem)); //映射虚拟地址后就可在用户空间使用
if (i2c->base == NULL) {
dev_err(&pdev->dev, "failure mapping io resources\n");
ret = -EBUSY;
goto err_unuse_clocks;
}
}
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
{
int i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if (type == resource_type(r) && num-- == 0)
return r;
}
return NULL;
}
EXPORT_SYMBOL_GPL(platform_get_resource);
int platform_get_irq(struct platform_device *dev, unsigned int num)
{
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
return r ? r->start : -ENXIO;
}
EXPORT_SYMBOL_GPL(platform_get_irq);
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
#
static inline resource_size_t resource_size(struct resource *res)
{
return res->end - res->start + 1;
}
struct resource * __request_region(struct resource *parent,
resource_size_t start, resource_size_t n,
const char *name, int flags)
{
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (!res)
return NULL;
res->name = name;
res->start = start;
res->end = start + n - 1;
res->flags = IORESOURCE_BUSY;
res->flags |= flags;
write_lock(&resource_lock);
for (;;) {
struct resource *conflict;
conflict = __request_resource(parent, res); //核心
if (!conflict)
break;
if (conflict != parent) {
parent = conflict;
if (!(conflict->flags & IORESOURCE_BUSY))
continue;
}
/* Uhhuh, that didn't work out.. */
kfree(res);
res = NULL;
break;
}
write_unlock(&resource_lock);
return res;
}
EXPORT_SYMBOL(__request_region);
static struct resource * __request_resource(struct resource *root, struct resource *new)
{
resource_size_t start = new->start;
resource_size_t end = new->end;
struct resource *tmp, **p;
if (end < start)
return root;
if (start < root->start)
return root;
if (end > root->end)
return root;
p = &root->child;
for (;;) {
tmp = *p;
if (!tmp || tmp->start > end) {
new->sibling = tmp;
*p = new;
new->parent = root;
return NULL;
}
p = &tmp->sibling;
if (tmp->end < start)
continue;
return tmp;
}
}