自学内容网 自学内容网

[linux 驱动]gpio子系统详解与实战

目录

1 描述

1.1 文件节点操作 gpio 引脚

1.2 gpio 引脚计算

2 结构体

2.1 gpio_desc

2.2 gpio_device

2.3 gpio_chip

3 相关函数

3.1 goio 申请释放

3.1.1 gpio_request

3.1.2 gpio_free

3.2 gpio 输入输出设置

3.2.1 gpio_direction_input

3.2.2 gpio_direction_output

3.3 gpio 值的获取与设置

3.3.1 gpio_get_value

3.3.2 gpio_set_value

3.4 与设备树相关

3.4.1 of_get_named_gpio_flags

3.4.1 of_get_named_gpio

4 示例


1 描述

1.1 文件节点操作 gpio 引脚

这里可以操作 gpio 引脚

zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~$ ls /sys/class/gpio/
export  unexport
zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~$

操作示例

echo  110 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio110/direction
cat /sys/class/gpio/gpio110/value
echo  110 > /sys/class/gpio/unexport

1.2 gpio 引脚计算

Core-3588J有5组 GPI0 bank:GPI00~GPI04,每组又以 A0~A7,B0-B7,C0-C7,D0-D7 作为编号区分,常用以下公式计算引脚:

GPI0 pin脚计算公式:pin=bank*32+number

GPI0 小组编号计算公式:number=group*8+X

bank=1;//GPl01 D0 => 1, bank e [0,4]
group = 3;//GPI01 D0=>3,group ∈{(A=0),(B=1),(C=2),(D=3)}X=0;//GPI01 D0 => 0, X ∈ [0,7]
number=group*8+X=3*8+ 0=24
pin= bank*32 +number=1*32 + 24 = 56:

2 结构体

2.1 gpio_desc

结构体 gpio_desc 是用于描述一个 GPIO (通用输入输出) 引脚的内部数据结构

96 struct gpio_desc { 
 97         struct gpio_device      *gdev;
 98         unsigned long           flags;
 99 /* flag symbols are bit numbers */
100 #define FLAG_REQUESTED  0
101 #define FLAG_IS_OUT     1
102 #define FLAG_EXPORT     2       /* protected by sysfs_lock */
103 #define FLAG_SYSFS      3       /* exported via /sys/class/gpio/control */
104 #define FLAG_ACTIVE_LOW 6       /* value has active low */
105 #define FLAG_OPEN_DRAIN 7       /* Gpio is open drain type */
106 #define FLAG_OPEN_SOURCE 8      /* Gpio is open source type */
107 #define FLAG_USED_AS_IRQ 9      /* GPIO is connected to an IRQ */
108 #define FLAG_IRQ_IS_ENABLED 10  /* GPIO is connected to an enabled IRQ */
109 #define FLAG_IS_HOGGED  11      /* GPIO is hogged */
110 #define FLAG_TRANSITORY 12      /* GPIO may lose value in sleep or reset */
111 #define FLAG_PULL_UP    13      /* GPIO has pull up enabled */
112 #define FLAG_PULL_DOWN  14      /* GPIO has pull down enabled */
113         
114         /* Connection label */
115         const char              *label;
116         /* Name of the GPIO */
117         const char              *name;
118 };

struct gpio_device *gdev;

指向与该 GPIO 引脚关联的 gpio_device 结构体的指针。gpio_device 结构体包含了与整个 GPIO 设备相关的信息。

unsigned long flags;

存储与 GPIO 引脚状态相关的标志位。这些标志位是以位域的形式存储,允许通过位运算快速检查或修改其状态。:

FLAG_REQUESTED (0):表示该 GPIO 引脚已被请求(占用)。

FLAG_IS_OUT (1):表示该 GPIO 引脚被配置为输出模式。

FLAG_EXPORT (2):表示该 GPIO 引脚已经通过 sysfs 导出,可以在用户空间访问。

FLAG_SYSFS (3):表示该 GPIO 引脚可以通过 /sys/class/gpio 接口进行控制。

FLAG_ACTIVE_LOW (6):表示该 GPIO 引脚为反相(即低电平有效)。

FLAG_OPEN_DRAIN (7):表示该 GPIO 引脚是开漏类型,通常用于与其他设备共享线。

FLAG_OPEN_SOURCE (8):表示该 GPIO 引脚是开源类型。

FLAG_USED_AS_IRQ (9):表示该 GPIO 引脚连接到一个中断请求(IRQ)。

FLAG_IRQ_IS_ENABLED (10):表示与该 GPIO 关联的中断已经启用。

FLAG_IS_HOGGED (11):表示该 GPIO 引脚被“霸占”,即被某个驱动独占使用。

FLAG_TRANSITORY (12):表示该 GPIO 引脚在睡眠或复位期间可能会丢失值。

FLAG_PULL_UP (13):表示该 GPIO 引脚启用了上拉电阻。

FLAG_PULL_DOWN (14):表示该 GPIO 引脚启用了下拉电阻。

const char *label;

一个指向字符的常量指针,用于描述该 GPIO 的连接标签。这在调试时非常有用,可以帮助开发人员了解 GPIO 的用途。

const char *name;

一个指向字符的常量指针,用于存储 GPIO 引脚的名称。这有助于在系统中识别和管理不同的 GPIO 引脚。

2.2 gpio_device

struct gpio_device 为 GPIO 设备提供了一个全面的描述,包括其基本属性、管理信息以及与其他内核子系统(如字符设备、Pin Control 等)的交互能力

44 struct gpio_device {
 45         int                     id;
 46         struct device           dev;
 47         struct cdev             chrdev;
 48         struct device           *mockdev;
 49         struct module           *owner;
 50         struct gpio_chip        *chip;
 51         struct gpio_desc        *descs;
 52         int                     base;
 53         u16                     ngpio;
 54         const char              *label;
 55         void                    *data;
 56         struct list_head        list;
 57 
 58 #ifdef CONFIG_PINCTRL
 59         /*
 60          * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
 61          * describe the actual pin range which they serve in an SoC. This
 62          * information would be used by pinctrl subsystem to configure
 63          * corresponding pins for gpio usage.
 64          */
 65         struct list_head pin_ranges;
 66 #endif
 67 };

int id;

GPIO 设备的唯一标识符,用于区分不同的 GPIO 设备。

struct device dev;

包含设备的基本信息,继承自 Linux 设备模型。这允许 GPIO 设备与内核的其他部分进行交互,如设备注册、驱动程序绑定等。

struct cdev chrdev;

用于表示字符设备的信息。这使得 GPIO 设备可以通过字符设备接口与用户空间进行通信。

struct device *mockdev;

指向一个模拟设备的指针,通常用于测试或开发环境中,以便在没有实际硬件时进行调试。

struct module *owner;

指向拥有该 GPIO 设备的模块的指针。它用于管理模块的生命周期,确保相关资源在模块卸载时被正确释放。

struct gpio_chip *chip

指向与该 GPIO 设备关联的 gpio_chip 结构体的指针。gpio_chip 结构体定义了具体的 GPIO 操作(如设置引脚状态、获取引脚状态等)。

struct gpio_desc *descs;

指向 gpio_desc 结构体数组的指针,存储与该 GPIO 设备相关的所有 GPIO 引脚的描述信息。

int base;

该 GPIO 设备管理的 GPIO 引脚的起始索引。用于确定引脚在全局 GPIO 空间中的位置。

u16 ngpio;

该 GPIO 设备所管理的 GPIO 引脚数量。

const char *label;

指向描述该 GPIO 设备的标签的字符串。这通常用于调试和日志记录,以便能快速识别设备的用途。

void *data;

一个指向用户自定义数据的指针,可以用于存储与 GPIO 设备相关的额外信息,供驱动程序或其他组件使用。

struct list_head list;

链表头,用于将该 GPIO 设备链接到其他设备的链表中。这使得可以方便地遍历系统中的所有 GPIO 设备。

struct list_head pin_ranges;

一个链表头,用于描述 GPIO 控制器所服务的引脚范围。这对于 Pin Controller 子系统来说非常重要,以便能够配置特定引脚的功能。

2.3 gpio_chip

struct gpio_chip 是一个核心结构体,它在 Linux 内核中提供了一种标准化的方式来管理和操作 GPIO 控制器。通过这个结构体,驱动程序能够简洁地进行 GPIO 的初始化、配置和读写操作。

340 struct gpio_chip {
341         const char              *label;
342         struct gpio_device      *gpiodev;
343         struct device           *parent;
344         struct module           *owner;
345 
346         int                     (*request)(struct gpio_chip *chip,
347                                                 unsigned offset);
348         void                    (*free)(struct gpio_chip *chip,
349                                                 unsigned offset);
350         int                     (*get_direction)(struct gpio_chip *chip,
351                                                 unsigned offset);
352         int                     (*direction_input)(struct gpio_chip *chip,
353                                                 unsigned offset);
354         int                     (*direction_output)(struct gpio_chip *chip,
355                                                 unsigned offset, int value);
356         int                     (*get)(struct gpio_chip *chip,
357                                                 unsigned offset);
358         int                     (*get_multiple)(struct gpio_chip *chip,
359                                                 unsigned long *mask,
360                                                 unsigned long *bits);
361         void                    (*set)(struct gpio_chip *chip,
362                                                 unsigned offset, int value);
363         void                    (*set_multiple)(struct gpio_chip *chip,
364                                                 unsigned long *mask,
365                                                 unsigned long *bits);
366         int                     (*set_config)(struct gpio_chip *chip,
367                                               unsigned offset,
368                                               unsigned long config);
369         int                     (*to_irq)(struct gpio_chip *chip,
370                                                 unsigned offset);
371 
372         void                    (*dbg_show)(struct seq_file *s,
373                                                 struct gpio_chip *chip);
374 
375         int                     (*init_valid_mask)(struct gpio_chip *chip,
376                                                    unsigned long *valid_mask,
377                                                    unsigned int ngpios);
378 
379         int                     base;
380         u16                     ngpio;
381         const char              *const *names;
382         bool                    can_sleep;
383 
384 #if IS_ENABLED(CONFIG_GPIO_GENERIC)
385         unsigned long (*read_reg)(void __iomem *reg);
386         void (*write_reg)(void __iomem *reg, unsigned long data);
387         bool be_bits;
388         void __iomem *reg_dat;
389         void __iomem *reg_set;
390         void __iomem *reg_clr;
391         void __iomem *reg_dir_out;
392         void __iomem *reg_dir_in;
393         bool bgpio_dir_unreadable;
394         int bgpio_bits;
395         spinlock_t bgpio_lock;
396         unsigned long bgpio_data;
397         unsigned long bgpio_dir;
398 #endif /* CONFIG_GPIO_GENERIC */
399 
400 #ifdef CONFIG_GPIOLIB_IRQCHIP
401         /*
402          * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
403          * to handle IRQs for most practical cases.
404          */
405 
406         /**
407          * @irq:
408          *
409          * Integrates interrupt chip functionality with the GPIO chip. Can be
410          * used to handle IRQs for most practical cases.
411          */
412         struct gpio_irq_chip irq;
413 #endif /* CONFIG_GPIOLIB_IRQCHIP */
414 
415         /**
416          * @valid_mask:
417          *
418          * If not %NULL holds bitmask of GPIOs which are valid to be used
419          * from the chip.
420          */
421         unsigned long *valid_mask;
422 
423 #if defined(CONFIG_OF_GPIO)
424         /*
425          * If CONFIG_OF is enabled, then all GPIO controllers described in the
426          * device tree automatically may have an OF translation
427          */
428 
429         /**
430          * @of_node:
431          *
432          * Pointer to a device tree node representing this GPIO controller.
433          */
434         struct device_node *of_node;
435 
436         /**
437          * @of_gpio_n_cells:
438          *
439          * Number of cells used to form the GPIO specifier.
440          */
441         unsigned int of_gpio_n_cells;
442 
443         /**
444          * @of_xlate:
445          *
446          * Callback to translate a device tree GPIO specifier into a chip-
447          * relative GPIO number and flags.
448          */
449         int (*of_xlate)(struct gpio_chip *gc,
450                         const struct of_phandle_args *gpiospec, u32 *flags);
451 #endif /* CONFIG_OF_GPIO */
452 };

3 相关函数

3.1 goio 申请释放

3.1.1 gpio_request

函数原型

int gpio_request(unsigned gpio, const char *label)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

const char *label

一个可选的标签,用于描述这个 GPIO 的用途。这个标签对于调试和日志记录非常有用,可以帮助开发人员识别不同的 GPIO 引脚及其功能。

返回值

int

成功:0 失败:负数

功能

申请 GPIO (通用输入输出) 引脚

 68 int gpio_request(unsigned gpio, const char *label)
 69 {
 70         struct gpio_desc *desc = gpio_to_desc(gpio); 
 71 
 72         /* Compatibility: assume unavailable "valid" GPIOs will appear later */
 73         if (!desc && gpio_is_valid(gpio))
 74                 return -EPROBE_DEFER;
 75 
 76         return gpiod_request(desc, label);
 77 }
2754 int gpiod_request(struct gpio_desc *desc, const char *label)
2755 {      
2756         int ret = -EPROBE_DEFER;
2757         struct gpio_device *gdev;
2758        
2759         VALIDATE_DESC(desc);
2760         gdev = desc->gdev;
2761        
2762         if (try_module_get(gdev->owner)) {
2763                 ret = gpiod_request_commit(desc, label);
2764                 if (ret < 0)
2765                         module_put(gdev->owner);
2766                 else
2767                         get_device(&gdev->dev);
2768         }
2769 
2770         if (ret)
2771                 gpiod_dbg(desc, "%s: status %d\n", __func__, ret);
2772 
2773         return ret;
2774 }

3.1.2 gpio_free

函数原型

void gpio_free(unsigned gpio)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

返回值

功能

释放 GPIO (通用输入输出) 引脚

 9 void gpio_free(unsigned gpio)
 10 {
 11         gpiod_free(gpio_to_desc(gpio));
 12 }
2810 void gpiod_free(struct gpio_desc *desc)
2811 {      
2812         if (desc && desc->gdev && gpiod_free_commit(desc)) {
2813                 module_put(desc->gdev->owner);
2814                 put_device(&desc->gdev->dev);
2815         } else {
2816                 WARN_ON(extra_checks);
2817         }
2818 }      

3.2 gpio 输入输出设置

3.2.1 gpio_direction_input

函数原型

int gpio_direction_input(unsigned gpio)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

返回值

功能

设置 GPIO (通用输入输出) 引脚为输入状态

 70 static inline int gpio_direction_input(unsigned gpio)
 71 {                                
 72         return gpiod_direction_input(gpio_to_desc(gpio));
 73 }      
2950 int gpiod_direction_input(struct gpio_desc *desc)
2951 {
2952         struct gpio_chip        *chip;
2953         int                     ret = 0;
2954 
2955         VALIDATE_DESC(desc);
2956         chip = desc->gdev->chip;
2957 
2958         /*
2959          * It is legal to have no .get() and .direction_input() specified if
2960          * the chip is output-only, but you can't specify .direction_input()
2961          * and not support the .get() operation, that doesn't make sense.
2962          */
2963         if (!chip->get && chip->direction_input) {
2964                 gpiod_warn(desc,
2965                            "%s: missing get() but have direction_input()\n",
2966                            __func__);
2967                 return -EIO;
2968         }
2969 
2970         /*
2971          * If we have a .direction_input() callback, things are simple,
2972          * just call it. Else we are some input-only chip so try to check the
2973          * direction (if .get_direction() is supported) else we silently
2974          * assume we are in input mode after this.
2975          */
2976         if (chip->direction_input) {
2977                 ret = chip->direction_input(chip, gpio_chip_hwgpio(desc));
2978         } else if (chip->get_direction &&
2979                   (chip->get_direction(chip, gpio_chip_hwgpio(desc)) != 1)) {
2980                 gpiod_warn(desc,
2981                            "%s: missing direction_input() operation and line is output\n",
2982                            __func__);
2983                 return -EIO;
2984         }
2985         if (ret == 0)
2986                 clear_bit(FLAG_IS_OUT, &desc->flags);
2987                   
2988         if (test_bit(FLAG_PULL_UP, &desc->flags))
2989                 gpio_set_config(chip, gpio_chip_hwgpio(desc),
2990                                 PIN_CONFIG_BIAS_PULL_UP);
2991         else if (test_bit(FLAG_PULL_DOWN, &desc->flags))
2992                 gpio_set_config(chip, gpio_chip_hwgpio(desc),
2993                                 PIN_CONFIG_BIAS_PULL_DOWN);
2994 
2995         trace_gpio_direction(desc_to_gpio(desc), 1, ret);
2996 
2997         return ret;
2998 }                    

3.2.2 gpio_direction_output

函数原型

int gpio_direction_output(unsigned gpio, int value)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

int value

GPIO 默认输出值

返回值

功能

设置 GPIO (通用输入输出) 引脚为输出状态

74 static inline int gpio_direction_output(unsigned gpio, int value)
 75 {
 76         return gpiod_direction_output_raw(gpio_to_desc(gpio), value);
 77 }
3055 int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
3056 {
3057         VALIDATE_DESC(desc);
3058         return gpiod_direction_output_raw_commit(desc, value);
3059 }

3.3 gpio 值的获取与设置

3.3.1 gpio_get_value

函数原型

int gpio_get_value(unsigned int gpio)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

返回值

功能

获取 GPIO (通用输入输出) 引脚的值

64 static inline int gpio_get_value(unsigned int gpio)
 65 {
 66         return __gpio_get_value(gpio);
 67 }

3.3.2 gpio_set_value

函数原型

void gpio_set_value(unsigned int gpio, int value)

参数

unsigned gpio

要请求的 GPIO 引脚的编号。该编号通常由硬件平台定义,具体的引脚编号可以查阅硬件文档。

int value

GPIO 值

返回值

功能

设置 GPIO (通用输入输出) 引脚值

 69 static inline void gpio_set_value(unsigned int gpio, int value)
 70 {
 71         __gpio_set_value(gpio, value);
 72 }   

3.4 与设备树相关

3.4.1 of_get_named_gpio_flags

函数原型

int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags)

参数

struct device_node *np

设备树节点指针

const char *list_name

GPIO属性名称

int index

属性值的索引

enum of_gpio_flags *flags

用于保存GPIO属性值的标志

返回值

int

成功:返回GPIO号 失败:负数

功能

从设备树中获取指定名称的GPIO列表中第index个GPIO的编号以及可能的标志

292 int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
293                             int index, enum of_gpio_flags *flags)
294 {                
295         struct gpio_desc *desc;
296 
297         desc = of_get_named_gpiod_flags(np, list_name, index, flags);
298 
299         if (IS_ERR(desc))
300                 return PTR_ERR(desc);
301         else     
302                 return desc_to_gpio(desc);
303 }       
253 static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
254                      const char *propname, int index, enum of_gpio_flags *flags)
255 {
256         struct of_phandle_args gpiospec;
257         struct gpio_chip *chip;
258         struct gpio_desc *desc;
259         int ret;
260 
261         ret = of_parse_phandle_with_args_map(np, propname, "gpio", index,
262                                              &gpiospec);
263         if (ret) {
264                 pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n",
265                         __func__, propname, np, index);
266                 return ERR_PTR(ret);
267         }
268 
269         chip = of_find_gpiochip_by_xlate(&gpiospec);
270         if (!chip) {
271                 desc = ERR_PTR(-EPROBE_DEFER);
272                 goto out;
273         }
274 
275         desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags);
276         if (IS_ERR(desc))
277                 goto out;
278 
279         if (flags)
280                 of_gpio_flags_quirks(np, propname, flags, index);
281 
282         pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n",
283                  __func__, propname, np, index,
284                  PTR_ERR_OR_ZERO(desc));
285 
286 out:     
287         of_node_put(gpiospec.np);
288 
289         return desc;
290 }                

3.4.1 of_get_named_gpio

函数原型

int of_get_named_gpio(struct device_node *np,const char *propname, int index)

参数

struct device_node *np

设备树节点指针

const char *propname

GPIO属性名称

int index

属性值的索引

返回值

int

成功:返回GPIO号 失败:负数

功能

从设备树中获取指定名称的GPIO列表中第index个GPIO的编号

129 static inline int of_get_named_gpio(struct device_node *np,
130                                    const char *propname, int index)
131 {
132         return of_get_named_gpio_flags(np, propname, index, NULL);
133 }   

4 示例

199 static int jw_io_control_probe(struct platform_device *pdev)
200 {
201         struct device_node *node = pdev->dev.of_node;
202         struct jw_io_pdata *pdata;
203         int ret;
204         enum of_gpio_flags flags;
205         printk(" #######jw_io_control_probe####### \n");
206         enable = 0 ;
207 
208         pdata = kzalloc(sizeof(struct jw_io_pdata), GFP_KERNEL);
209         if (pdata == NULL) {
210                 printk("%s failed to allocate driver data\n",__FUNCTION__);
211                 return -ENOMEM;
212         }
213         memset(pdata,0,sizeof(struct jw_io_pdata));
214 
320                 ret = of_get_named_gpio_flags(node, "led_ctl", 0, &flags);
321                 if (ret < 0) {
322                         printk("%s() Can not read property usb_5v_gpio\n", __FUNCTION__);
323                         goto err;
324                 } else {
325                         pdata->led_gpio = ret;
326                         ret = devm_gpio_request(&pdev->dev, pdata->led_gpio, "led_gpio");
327                         if(ret < 0){
328                                 printk("%s() devm_gpio_request led_gpio request ERROR\n", __FUNCTION__);
329                                 goto err;
330                         }
331 
332                         ret = gpio_direction_output(pdata->led_gpio,0);
333                         if(ret < 0){
334                                 printk("%s() gpio_direction_input led_gpio set ERROR\n", __FUNCTION__);
335                                 goto err;
336                         }
337                 }
360 
376 
377          ret = device_create_file(&pdev->dev, &dev_attr_led_display);
378          if (ret) {
379                 printk(KERN_ERR "%s:Fail to creat led_display class file\n", __func__);
380                         return ret;
381           }else
382                 printk("class_create jw_io_control led OK !!!!\n");
383 
390 
391         JWpdata_info = pdata;
392         printk(" #######jw_io_control_probe end####### \n");
393         return 0;
394 err:
395         kfree(pdata);
396         return ret;
397 }

原文地址:https://blog.csdn.net/weixin_49406449/article/details/142956032

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!