linux 3.10内核分析,基于Linux 3.10.49内核的gpio流程分析

Linux kernel 3.10.49+

在这里, 我们说说linux 是怎么通过platform_driver驱动代码匹配到platform_device的.

static const struct of_device_id ***_gpio_of_match[] = {

{ .compatible = "******,***-gpio", },        // 这个字符串就是dts里的compatible字符串

{}

};

MODULE_DEVICE_TABLE(of, ***_gpio_of_match);

static struct platform_driver ***_gpio_driver = {

.probe = ***_gpio_probe,                    // 匹配完成后, 运行的probe函数, 可以做一些初始化.

.driver = {

.name = "***_gpio",

.owner = THIS_MODULE,

.of_match_table = ***_gpio_of_match,

},

};

module_platform_driver(***_gpio_driver);

1. drivers/gpio/gpio-***.c : module_platform_driver(***_gpio_driver);  // gpio驱动入口

2. include/linux/platform_device.h 宏 : module_platform_driver

#define module_platform_driver(__platform_driver) \

module_driver(__platform_driver, platform_driver_register, \

platform_driver_unregister)

3. drivers/base/platform.c : platform_driver_register(...)

drv->driver.bus = &platform_bus_type;

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);

4. drivers/base/driver.c : driver_register(...)

...

ret = bus_add_driver(drv);

...

5. drivers/base/bus.c : bus_add_driver(...)

...

error = driver_attach(drv);

...

6. drivers/base/bus.c : driver_attach(...)

int driver_attach(struct device_driver *drv)

{

return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

7. drivers/base/dd.c : bus_for_each_dev(...)

...

klist_iter_init_node(&bus->p->klist_devices, &i,

(start ? &start->p->knode_bus : NULL));

while ((dev = next_device(&i)) && !error)    // 这个就是全局变量中, 所有已经进行过注册的device.

// 在上一篇 基于Linux 3.10.49内核 从dts文件里注册platform_device流程分析 已介绍过 http://www.linuxidc.com/Linux/2017-10/147522.htm

error = fn(dev, data);          // fn 就是 __driver_attach 函数指针. 轮询device进行匹配.

klist_iter_exit(&i);

...

8. drivers/base/dd.c : __driver_attach(...)

...

if (!driver_match_device(drv, dev)) // 匹配成功, 返加非0, 否则返回0. // 跳到第8-1-1步

return 0;

if (dev->parent)    /* Needed for USB */  // 有父设备, 父设备也就加锁

device_lock(dev->parent);

device_lock(dev);        // 设备加锁

if (!dev->driver)        // 如果device没有驱动程序, 就driver_probe_device

driver_probe_device(drv, dev);          //  跳到第8-2-1步

device_unlock(dev);      // 设备释放锁

if (dev->parent)          // 有父设备, 父设备也就释放锁

device_unlock(dev->parent);

return 0

8-1-1. drivers/base/base.h : driver_match_device(...)

static inline int driver_match_device(struct device_driver *drv,

struct device *dev)

{

return drv->bus->match ? drv->bus->match(dev, drv) : 1;

}

// drv->bus 就是 第三步的 drv->driver.bus = &platform_bus_type;

// 也就是相当于platform_bus_type->match(dev, drv);

// struct bus_type platform_bus_type = {    // drivers/base/platform.c

//    .name        = "platform",

//    .dev_attrs    = platform_dev_attrs,

//    .match        = platform_match,

//    .uevent        = platform_uevent,

//    .pm        = &platform_dev_pm_ops,

// };

// EXPORT_SYMBOL_GPL(platform_bus_type);

// 也就是platform_match(dev, drv);

8-1-2. drivers/base/platform.c : platform_match(...)

static int platform_match(struct device *dev, struct device_driver *drv)

{

...

if (of_driver_match_device(dev, drv))

return 1;

...

}

8-1-3. include/linux/of_device.h : of_driver_match_device(...)

static inline int of_driver_match_device(struct device *dev,

const struct device_driver *drv)

{

return of_match_device(drv->of_match_table, dev) != NULL;  // 也就是***_gpio_of_match

}

of_match_device(...) --> of_match_node(...)

of_match_node(...) --> __of_match_node(...)

static const struct of_device_id *__of_match_node(const struct of_device_id *matches,

const struct device_node *node)  // matches 就是drv->of_match_table, 也就是***_gpio_of_match

{

if (!matches)

return NULL;

while (matches->name[0] || matches->type[0] || matches->compatible[0]) {

int match = 1;

if (matches->name[0])

match &= node->name

&& !strcmp(matches->name, node->name);

if (matches->type[0])

match &= node->type

&& !strcmp(matches->type, node->type);

if (matches->compatible[0])

match &= __of_device_is_compatible(node,    // 匹配 compatible

matches->compatible);    // ***_gpio_of_match.compatible 与 device node 的 compatible 匹配

if (match)

return matches;

matches++;

}

return NULL;

}

static int __of_device_is_compatible(const struct device_node *device,

const char *compat)

{

const char* cp;

int cplen, l;

cp = __of_get_property(device, "compatible", &cplen);  // 这里就是获取device的compatible的字符串信息

if (cp == NULL)

return 0;

while (cplen > 0) {

if (of_compat_cmp(cp, compat, strlen(compat)) == 0)  // 对比device的compatible的字符串信息和driver的compatible的字符串信息是否相等

return 1;

l = strlen(cp) + 1;

cp += l;

cplen -= l;

}

return 0;

}

8-2-1. drivers/base/dd.c : driver_probe_device(...)

driver_probe_device(...) --> really_probe(...)

8-2-2. drivers/base/dd.c : really_probe(...)

...

dev->driver = drv;  // 驱动 赋值给 设备.

pinctrl_bind_pins();    // 跳到第8-2-2-1-1步

...

if (dev->bus->probe) {

ret = dev->bus->probe(dev);

if (ret)

goto probe_failed;

} else if (drv->probe) {

ret = drv->probe(dev);  // 前面platform_driver_register(...)时  drv->driver.probe = platform_drv_probe, 所以进入platform_drv_probe

// 跳到第8-2-2-2-1步

if (ret)

goto probe_failed;

}

driver_bound(dev);          // 驱动挷定设备

8-2-2-1-1. drivers/base/pinctrl.c : pinctrl_bind_pins(...)

dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);

if (!dev->pins)

return -ENOMEM;

dev->pins->p = devm_pinctrl_get(dev);  // 调用 pinctrl_get(...) --> create_pinctrl(...)

// 又进入到pinctrl子系统代码中

// 在create_pinctrl(...)里

// p->states, p->dt_maps都为空, 只有pinctrl-0的dts节点设备才不为空, 具体查看, pinctrl驱动初始化

// 具体查看 基于linux 3.10.49内核的pinctrl流程分析 补充 已介绍过  http://www.linuxidc.com/Linux/2017-10/147521p2.htm

// 加入到list_add_tail(&p->node, &pinctrl_list);

// 每一个驱动注册时, alloc的struct pinctrl都会加入到全局变量pinctrl_list列表中.

if (IS_ERR(dev->pins->p)) {

dev_dbg(dev, "no pinctrl handle\n");

ret = PTR_ERR(dev->pins->p);

goto cleanup_alloc;

}

dev->pins->default_state = pinctrl_lookup_state(dev->pins->p,

PINCTRL_STATE_DEFAULT);        // gpio是没有state, 一般只有pinctrl-0的dts节点设备才存在.

if (IS_ERR(dev->pins->default_state)) {

dev_dbg(dev, "no default pinctrl state\n");

/* printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>> dev_name(dev) = %s\n", dev_name(dev)); */

ret = 0;

goto cleanup_get;                          // 没有state, ret = 0; 直接goto cleanup_get;

}

8-2-2-2-1. drivers/base/platform.c : platform_drv_probe(...)

...

ret = drv->probe(dev);    //  struct platform_driver ***_gpio_driver的probe函数.也就是***_gpio_probe, 最终目的来到这里.可以自定义写代码了.

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值