15 内核里leds-gpio设备驱动的设备树方法

来源:互联网 发布:java,建立string 编辑:程序博客网 时间:2024/05/19 16:49

在linux内核里已提供了连接到gpio的led设备驱动,只需要通过platform_device或设备提供相应的硬件资源即可.
使用platform_device方法可参考: http://blog.csdn.net/jklinux/article/details/73850470

内核里的leds-gpio设备驱动配置选项:

make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  Device Drivers  --->    -*- LED Support  --->      <*>   LED Support for GPIO connected LEDs通过配置选项的帮助信息可以查出对应的设备驱动源文件: drivers/leds/leds-gpio.c 


leds-gpio.c源文件里设备树相关的主要内容:

274 static struct platform_driver gpio_led_driver = {275     .probe      = gpio_led_probe,276     .shutdown   = gpio_led_shutdown,277     .driver     = {278         .name   = "leds-gpio",279         .of_match_table = of_gpio_leds_match,280     },281 };223 static const struct of_device_id of_gpio_leds_match[] = {224     { .compatible = "gpio-leds", },225     {},226 };227 228 MODULE_DEVICE_TABLE(of, of_gpio_leds_match);这两部分内容可得知,此设备驱动是一个platform_driver的对象,可通过platform_device或设备树里的设备节点来匹配。设备节点里的compatible属性值应是"gpio-leds".

匹配上后, 设备驱动里gpio_led_probe函数就会被触发调用. 在probe函数里就会取出设备树里提供的硬件资源.230 static int gpio_led_probe(struct platform_device *pdev)231 {232     struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); //使用设备树的方式, pdata应为NULL;233     struct gpio_leds_priv *priv;234     int i, ret = 0;235 236     if (pdata && pdata->num_leds) {        ... //使用platform_device方式的获取硬件资源的处理代码251     } else {252         priv = gpio_leds_create(pdev); //使用设备树时的处理代码253         if (IS_ERR(priv))254             return PTR_ERR(priv);255     }

在gpio_leds_create函数里获取设备节点的资源156 static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)157 {158     struct device *dev = &pdev->dev;159     struct fwnode_handle *child;160     struct gpio_leds_priv *priv;161     int count, ret;162 163     count = device_get_child_node_count(dev); //获取子节点的个数, 意味着设备节点里是需要包含子节点的,并不是使用设备节点的属性来的提供资源.164     if (!count)165         return ERR_PTR(-ENODEV);166 167     priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);168     if (!priv)169         return ERR_PTR(-ENOMEM);171     device_for_each_child_node(dev, child) { //遍历设备节点里的每一个子节点172         struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];173         struct gpio_led led = {};174         const char *state = NULL;175         struct device_node *np = to_of_node(child);176 177         ret = fwnode_property_read_string(child, "label", &led.name); //获取子节点的label属性值. 意味着每个子节点应有一个label属性,属性值应为字符串.178         if (ret && IS_ENABLED(CONFIG_OF) && np)179             led.name = np->name;180         if (!led.name) {181             fwnode_handle_put(child);182             return ERR_PTR(-EINVAL);183         }184         //获取子节点里的gpio口信息. con_id为NULL,意味着子节点应是使用gpios属性来提供led所连接的io口信息. 而且这里仅是获取一个io口信息,并不是多个io口,意味着每个子节点表示一个led灯的资源185         led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,186                                  GPIOD_ASIS,187                                  led.name);188         if (IS_ERR(led.gpiod)) { //获取io口失败则返回错误码189             fwnode_handle_put(child);190             return ERR_CAST(led.gpiod);191         }192         //下面的属性应是可选设置的,因并没有不设值而返回错误码.193         fwnode_property_read_string(child, "linux,default-trigger",194                         &led.default_trigger);196         if (!fwnode_property_read_string(child, "default-state",197                          &state)) {198             if (!strcmp(state, "keep"))199                 led.default_state = LEDS_GPIO_DEFSTATE_KEEP;200             else if (!strcmp(state, "on"))201                 led.default_state = LEDS_GPIO_DEFSTATE_ON;202             else203                 led.default_state = LEDS_GPIO_DEFSTATE_OFF;204         }205 206         if (fwnode_property_present(child, "retain-state-suspended"))207             led.retain_state_suspended = 1;208         if (fwnode_property_present(child, "panic-indicator"))209             led.panic_indicator = 1;210 211         ret = create_gpio_led(&led, led_dat, dev, NULL);212         if (ret < 0) {213             fwnode_handle_put(child);214             return ERR_PTR(ret);215         }216         led_dat->cdev.dev->of_node = np;217         priv->num_leds++;218     }219 220     return priv;221 }

现板上的STATUS-LED连接到PA17, PWR-LED连接到PL10.
综上所述,关于leds-gpio设备驱动的设备树可:

myleds {    compatible = "gpio-leds";    superled0 {        label = "led0";        gpios = <&pio  0  17  GPIO_ACTIVE_HIGH>;    };    superled1 {        label = "led1";        gpios = <&r_pio  0  10  GPIO_ACTIVE_HIGH>;    };};  


重编设备树并更新后启动系统, 然后就可以查看到myleds设备节点产生platform_device信息:^_^ / # ls /sys/bus/platform/devices/myleds/driver/          leds/            of_node/         subsystem/driver_override  modalias         power/           uevent//看到有driver目录即表示已与platform_driver匹配上了.^_^ / # ls /sys/bus/platform/devices/myleds/leds/ledled0/  led1/    //表示在led子系统里会创建出/sys/class/leds/led0   /sys/class/leds/led1目录控制led:echo 1 > /sys/class/leds/led0/brightness   // label为led0的led灯亮echo 0 > /sys/class/leds/led0/brightness   // label为led0的led灯灭

如无法通过代码分析出设备树里应怎样描述设备,可以参考内核源码里的:Documentation/devicetree/bindings/leds/leds-gpio.txt

阅读全文
0 0
原创粉丝点击