在上文中分析了gpio-led platform_device是如何定义并注册的。

那么gpio-led platform_device 和 gpio-led platform_driver是如何匹配的呢

我们还是先分析probe函数

drivers\leds\leds-gpio.c

static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_leds_priv *priv;
int i, ret = 0; if (pdata && pdata->num_leds) {
priv = devm_kzalloc(&pdev->dev,
sizeof_gpio_leds_priv(pdata->num_leds),
GFP_KERNEL);
if (!priv)
return -ENOMEM; priv->num_leds = pdata->num_leds;
for (i = 0; i < priv->num_leds; i++) {
ret = create_gpio_led(&pdata->leds[i], &priv->leds[i],
&pdev->dev, NULL,
pdata->gpio_blink_set);
if (ret < 0)
return ret;
}
} else {
priv = gpio_leds_create(pdev);
if (IS_ERR(priv))
return PTR_ERR(priv);
} platform_set_drvdata(pdev, priv); return 0;
}

接着看gpio_leds_create()函数

static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fwnode_handle *child;
struct gpio_leds_priv *priv;
int count, ret;
count = device_get_child_node_count(dev);
if (!count)
return ERR_PTR(-ENODEV);
priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
if (!priv)
return ERR_PTR(-ENOMEM);
device_for_each_child_node(dev, child) {
struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];
struct gpio_led led = {};
const char *state = NULL;
struct device_node *np = to_of_node(child);
ret = fwnode_property_read_string(child, "label", &led.name);
if (ret && IS_ENABLED(CONFIG_OF) && np)
led.name = np->name;
if (!led.name) {
fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
GPIOD_ASIS,
led.name);
if (IS_ERR(led.gpiod)) {
fwnode_handle_put(child);
return ERR_CAST(led.gpiod);
}
fwnode_property_read_string(child, "linux,default-trigger",
&led.default_trigger);
if (!fwnode_property_read_string(child, "default-state",
&state)) {
if (!strcmp(state, "keep"))
led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
else if (!strcmp(state, "on"))
led.default_state = LEDS_GPIO_DEFSTATE_ON;
else
led.default_state = LEDS_GPIO_DEFSTATE_OFF;
}
if (fwnode_property_present(child, "retain-state-suspended"))
led.retain_state_suspended = 1;
if (fwnode_property_present(child, "retain-state-shutdown"))
led.retain_state_shutdown = 1;
if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
ret = create_gpio_led(&led, led_dat, dev, np, NULL);
if (ret < 0) {
fwnode_handle_put(child);
return ERR_PTR(ret);
}
led_dat->cdev.dev->of_node = np;
priv->num_leds++;
}
return priv;
}

其中,

ret = fwnode_property_read_string(child, "label", &led.name);
led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
GPIOD_ASIS,
led.name);
fwnode_property_read_string(child, "linux,default-trigger",
&led.default_trigger);

最后调用create_gpio_led()函数创建led

ret = create_gpio_led(&led, led_dat, dev, np, NULL);

那么设备树中的gpio定义是如何传递到设备中的呢

接着分析gpio_leds_create中调用的devm_fwnode_get_gpiod_from_child()函数

先看一段定义

drivers/gpio/gpiolib.h

/* gpio suffixes used for ACPI and device tree lookup */
static const char * const gpio_suffixes[] = { "gpios", "gpio" };

devm_fwnode_get_gpiod_from_child调用一系列函数, 创建gpio_desc

fwnode_get_named_gpiod
gpiod_get_from_of_node

最后调用devres_add将gpio_desc作为device resource 注册给leds-gpio platfor_device

devres_add(dev, dr);

leds-gpio driver 续1的更多相关文章

  1. 调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之二

    /** ****************************************************************************** * @author    暴走的小 ...

  2. 调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之一

    /** ****************************************************************************** * @author    暴走的小 ...

  3. 调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之三

    /** ****************************************************************************** * @author    暴走的小 ...

  4. Davinci DM6446开发攻略——LINUX GPIO驱动源码移植

    一.             DM6446 GPIO的介绍      说到LINUX 驱动移植,没有移植过的朋友,或刚刚进入LINUX领域的朋友,最好去看看<LINUX 设备驱动程序>第三 ...

  5. am335x system upgrade kernel gpio(九)

    1      Hardware Overview gpio interface,pin map: AM335X_I2C0_W_C----------------------MCASP0_AXR1 /* ...

  6. ok6410 android driver(9)

    In this essay, I will write the JNI to test our leds device. If you don't know how to create a jni p ...

  7. linux内核中的GPIO系统之(2):pin control subsystem

    一.前言 在linux2.6内核上工作的嵌入式软件工程师在pin control上都会遇到这样的状况: (1)启动一个新的项目后,需要根据硬件平台的设定进行pin control相关的编码.例如:在b ...

  8. linux内核中的GPIO系统之(1):软件框架

    一.前言 作为一个工作多年的系统工程师,免不了做两件事情:培训新员工和给新员工分配任务.对于那些刚刚从学校出来的学生,一般在开始的时候总是分配一些非常简单的任务,例如GPIO driver.LED d ...

  9. 转字符驱动实例gpio

    概述: 字符设备驱动程序: 是按照字符设备要求完成的由操作系统调用的代码. 重点理解以下内容:  1. 驱动是写给操作系统的代码,它不是直接给用户层程序调用的,而是给系统调用的  2. 所以驱动要向系 ...

随机推荐

  1. Linux 常用命令四 rmdir rm

    一.rmdir命令 用于删除空目录: wang@wang:~/workpalce/python$ tree . ├── .txt ├── .txt ├── .txt ├── A │   └── B │ ...

  2. bzoj 1112: [POI2008]砖块Klo【对顶堆】

    priority_queue实现的对顶堆,细节超级多WA了十几次--但是理论上是最简便的orz其实是我已经不会写平衡树了 枚举左端点,显然要把这一段的高度搞成(l,l+k-1)的高度中位数,所以需要一 ...

  3. bzoj 4500: 矩阵【差分约束】

    (x,y,z)表示格子(x,y)的值为z,也就是x行+y列加的次数等于z,相当于差分约束的条件,用dfs判断冲突即可. #include<iostream> #include<cst ...

  4. Poj 3264 Balanced Lineup RMQ模板

    题目链接: Poj 3264 Balanced Lineup 题目描述: 给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值. 解题思路: 很模板的RMQ模板题,在这 ...

  5. [USACO 2011 Dec Gold] Threatening Letter【后缀】

    Problem 3: Threatening Letter [J. Kuipers, 2002] FJ has had a terrible fight with his neighbor and w ...

  6. Service官方教程(11)Bound Service示例之2-AIDL 定义跨进程接口并通信

    Android Interface Definition Language (AIDL) 1.In this document Defining an AIDL Interface Create th ...

  7. HTTP协议 之 缓存

    转自:  http://www.cnblogs.com/TankXiao/archive/2012/11/28/2793365.html HTTP协议提供了非常强大的缓存机制, 了解这些缓存机制,对提 ...

  8. jmeter(七)函数

    JMeter函数是一些能够转化在测试树中取样器或者其他配置元件的域的特殊值.一个函数的调用就像这样:${_functionName(var1,var2,var3)},-functionName匹配函数 ...

  9. Cenos7 切换单用户模式

    CentOS 7在进入单用户的时候和6.x做了很多改变,下面让我们来看看如何进入单用户. 1.重启服务器,在选择内核界面使用上下箭头移动 2.选择内核并按“e” 3.修改参数 将rhgb quiet ...

  10. 开发一个 Web App 必须了解的那些事

    在过去的一年里,我在从头开始开发我的第一个重要的Web应用.经验教会了很多以前不知道的东西,特别是在安全性和用户体验方面. 值得一提的是,我上一次尝试构建的任何合理复杂性是在2005年.所以,在安全防 ...