at91 linux 4.1.0下dts驱动编程模型

Posted 凌云物网智科实验室

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了at91 linux 4.1.0下dts驱动编程模型相关的知识,希望对你有一定的参考价值。

下面的这个驱动文件at91_keyled.c在Atmel提供的linux-at91-linux4sam_5.3下实现了按键控制LED的亮灭过程,通过这个简单的驱动描述了基于DTS的驱动开发模型以及Linux内核里的GPIO相关的操作函数。

 

  1 /*********************************************************************************
  2  *      Copyright:  (C) 2016 Guo Wenxue<[email protected]>  
  3  *                  All rights reserved.
  4  *
  5  *       Filename:  at91_keyled.c
  6  *    Description:  This is a sample driver for GPIO operation with DTS linux on at91,
  7  *                  which willl turn led on when a button pressed.
  8  *                 
  9  *        Version:  1.0.0(2016-6-29~)
 10  *         Author:  Guo Wenxue <[email protected]>
 11  *      ChangeLog:  1, Release initial version on "Wed Jun 29 12:00:44 CST 2016"
 12  *
 13  *
 14  *    DTS Changes:
 15  *                 add keyleds support in arch/arm/boot/dts/at91sam9x5cm.dtsi
 16  *
 17  *                   keyleds{
 18  *                          compatible = "key-leds";
 19  *                          gpios = <&pioB 18 GPIO_ACTIVE_LOW     priv->pin_key=of_get_gpio(pdev->dev.of_node, 0);
 20  *                                   &pioB 16 GPIO_ACTIVE_LOW>;   priv->pin_key=of_get_gpio(pdev->dev.of_node, 1);
 21  *                          status = "okay";
 22  *                   }
 23  *
 24  *                   1wire_cm {
 25  *                      ... ...
 26  *                      ... ...
 27  *                   }
 28  *                 
 29  ********************************************************************************/
 30 
 31 #include <linux/module.h>
 32 #include <linux/moduleparam.h>
 33 #include <linux/platform_device.h>
 34 
 35 #include <linux/of.h>
 36 #include <linux/of_device.h>
 37 #include <linux/of_gpio.h>
 38 #include <linux/delay.h>
 39 #include <linux/gpio.h>
 40 #include <linux/interrupt.h>
 41 
 42 typedef struct keyled_priv_s 
 43 {
 44     int       pin_key;  
 45     int       pin_led; 
 46     int       led_status;
 47 } keyled_priv_t;  /*---  end of struct keyled_priv_s  ---*/
 48 
 49 
 50 static const struct of_device_id of_key_leds_match[] = {
 51         { .compatible = "key-leds", },
 52         {},
 53 };
 54 MODULE_DEVICE_TABLE(of, of_key_leds_match);
 55 
 56 
 57 static irqreturn_t key_detect_interrupt(int irq, void *dev_id)
 58 {
 59     keyled_priv_t    *priv = (keyled_priv_t *)dev_id;
 60 
 61     priv->led_status ^= 1;
 62     gpio_set_value(priv->pin_led, priv->led_status);
 63 
 64     return IRQ_HANDLED;
 65 }
 66 
 67 
 68 static int at91_keyled_probe(struct platform_device *pdev)
 69 {
 70     int              res;
 71     keyled_priv_t    *priv;
 72 
 73     printk(KERN_INFO "at91_keyled driver probe\n");
 74 
 75     if( 2 != of_gpio_count(pdev->dev.of_node) )
 76     {
 77         printk(KERN_ERR "keyled pins definition in dts invalid\n");
 78         return -EINVAL;
 79     }
 80 
 81     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 82     if(!priv)
 83         return -ENOMEM;
 84 
 85     platform_set_drvdata(pdev, priv);
 86 
 87     priv->pin_key=of_get_gpio(pdev->dev.of_node, 0);
 88     priv->pin_led=of_get_gpio(pdev->dev.of_node, 1);
 89 
 90     if( gpio_is_valid(priv->pin_key) )
 91     {
 92         if( (res=devm_gpio_request(&pdev->dev, priv->pin_key, "keyled_key")) < 0 )
 93         {
 94             dev_err(&pdev->dev, "can‘t request key gpio %d\n", priv->pin_key);
 95             return res;
 96         }
 97         dev_info(&pdev->dev, "request key gpio %d ok\n", priv->pin_key);
 98 
 99         if( (res=gpio_direction_input(priv->pin_key)) < 0 )
100         {
101             dev_err(&pdev->dev, "can‘t request input direction key gpio %d\n", priv->pin_key);
102             return res;
103         }
104         dev_info(&pdev->dev, "request input direction key gpio %d ok\n", priv->pin_key);
105 
106         printk(KERN_INFO "Key gpio current status: %d\n", gpio_get_value(priv->pin_key));
107 
108         res = request_irq( gpio_to_irq(priv->pin_key), key_detect_interrupt, IRQF_TRIGGER_FALLING, "keyled", priv);
109         if( res )
110         {
111             dev_err(&pdev->dev, "can‘t request IRQ<%d> for key gpio %d\n", gpio_to_irq(priv->pin_key), priv->pin_key);
112             return -EBUSY;
113         }
114         dev_info(&pdev->dev, "request IRQ<%d> for key gpio %d ok\n", gpio_to_irq(priv->pin_key), priv->pin_key);
115     }
116 
117     if( gpio_is_valid(priv->pin_led) )
118     {
119         if( (res=devm_gpio_request(&pdev->dev, priv->pin_led, "keyled_led")) < 0 )
120         {
121             dev_err(&pdev->dev, "can‘t request key gpio %d\n", priv->pin_led);
122             return res;
123         }
124 
125         if( (res=gpio_direction_output(priv->pin_led, 0)) < 0 )
126         {
127             dev_err(&pdev->dev, "can‘t request output direction key gpio %d\n", priv->pin_led);
128             return res;
129         }
130     }
131 
132     return 0;
133 }
134 
135 static int at91_keyled_remove(struct platform_device *pdev)
136 {
137     keyled_priv_t    *priv = platform_get_drvdata(pdev);
138 
139     printk(KERN_INFO "at91_keyled driver remove\n");
140 
141     devm_gpio_free(&pdev->dev, priv->pin_led);
142     devm_gpio_free(&pdev->dev, priv->pin_key);
143 
144     free_irq(gpio_to_irq(priv->pin_key), priv);
145 
146     devm_kfree(&pdev->dev, priv);
147 
148     return 0;
149 }
150 
151 static struct platform_driver at91_keyled_driver = {
152     .probe      = at91_keyled_probe,
153     .remove     = at91_keyled_remove,
154     .driver     = {
155         .name   = "key-leds",
156         .of_match_table = of_key_leds_match,
157     },
158 };
159 
160 module_platform_driver(at91_keyled_driver);
161 
162 MODULE_AUTHOR("guowenxue <[email protected]>");
163 MODULE_DESCRIPTION("AT91 Linux DTS GPIO driver for Key and LED");
164 MODULE_LICENSE("GPL");
165 MODULE_ALIAS("platform:key-leds");

 

以上是关于at91 linux 4.1.0下dts驱动编程模型的主要内容,如果未能解决你的问题,请参考以下文章

旧文-16C554在LINUX上的移植(AT91)-2010年06月24日 11:29

linux驱动注册汇总

Android系统 linux内核按键驱动开发

SylixOS 基于AT91SAM9X25的CAN总线传输流程解析

设备树学习笔记

从DTS到驱动加载的过程分析