uboot GPIO Framework

1.DM_GPIO 架构图
在这里插入图片描述

1.1.框架说明

  • gpio core 功能(在gpio uclass中实现):

    • 主要是为上层提供接口
    • 从dts中获取GPIO属性
    • 从gpio uclass的设备链表中获取到相应的udevice设备,并使用其操作集
  • gpio uclass

    • 链接属于该uclass的所有gpio udevice设备
    • 为gpio udevice的driver提供统一的操作集接口
  • bank和gpio

    • 有些平台上,将某些使用同一组寄存器的gpio构成一个bank
    • 不是所有平台都有bank的概念,例如高通,高通的GPIO都有自己独立的寄存器,因此,可以将高通当成只有一个bank
  • gpio udevice

    • 一个bank对应一个gpio udevice,用bank中的偏移来表示具体的GPIO号
    • gpio udevice的driver就会根据bank以及offset对相应的寄存器上的相应的bit进行操作。

1.2.gpio的工作原理介绍

  • 一个bank对应一个udevice,udevice中私有数据中存放着该bank的信息,比如相应寄存器地址等等
  • 上层用gpio_desc描述符来描述一个GPIO,其中包括该GPIO所属的udevice、在bank内的偏移、以及标志位。
  • 上层通过调用gpio core的接口从dtsi获取到GPIO属性对应的gpio_desc描述符
  • 上层使用gpio_desc描述符来作为调用gpio core的操作接口的参数
  • gpio core从gpio_desc描述符提取udevice,并调用其driver中对应的操作集,以bank内的偏移作为其参数(这样driver就能判断出是哪个GPIO了)
  • driver中提取udevice的私有数据中的bank信息,并进行相应的操作

2.gpio uclass

gpio uclass实现了两部分:

  • gpio uclass driver:gpio uclass驱动,提供gpio udevice绑定到uclass的设备链表之前和之后的一些操作,以及udevice的driver的操作集规范。
  • gpio core:为上层提供GPIO的操作接口

2.1.宏配置

CONFIG_DM=y
CONFIG_DM_GPIO=y
CONFIG_CMD_GPIO=y

2.2.重要结构体

  1).struct gpio_desc :上层是通过gpio_desc来和gpio core进行交互的。

117 struct gpio_desc {
118     struct udevice *dev;    /* Device, NULL for invalid GPIO */
119     unsigned long flags;
120 #define GPIOD_REQUESTED     (1 << 0)    /* Requested/claimed */
121 #define GPIOD_IS_OUT        (1 << 1)    /* GPIO is an output */
122 #define GPIOD_IS_IN     (1 << 2)    /* GPIO is an input */
123 #define GPIOD_ACTIVE_LOW    (1 << 3)    /* value has active low */
124 #define GPIOD_IS_OUT_ACTIVE (1 << 4)    /* set output active */
125 
126     uint offset;        /* GPIO offset within the device */
131 };
  • 老版本是offset+bank的gpio_base获得具体GPIO number
  • DM gpio是通过调用uclass的接口函数从dts直接获得对应GPIO的描述符

  2).struct gpio_dev_priv

  每个gpio uclass设备链表下的udevice都有一部分属于uclass的私有数据:udevice->uclass_priv,提供给gpio uclass使用,让gpio uclass知道这个udevice中的gpio信息和情况。

struct gpio_dev_priv {
    const char *bank_name;  // udevice的名字,也是bank名称
    unsigned gpio_count; // 这个bank中的GPIO数量
    unsigned gpio_base; // 每个bank的gpio都占有gpio uclass的一部分连续的gpio空间,gpio_base则表示该bank的第一个GPIO号。
    char **name;       //  阵列,每个gpio被request之后,都会有自己的label名称,存储在这里,可以防止GPIO request冲突

  3).操作集dm_gpio_ops

struct dm_gpio_ops {
    int (*request)(struct udevice *dev, unsigned offset, const char *label); 
    int (*free)(struct udevice *dev, unsigned offset);
    int (*direction_input)(struct udevice *dev, unsigned offset);
    int (*direction_output)(struct udevice *dev, unsigned offset,
                int value);
    int (*get_value)(struct udevice *dev, unsigned offset);
    int (*set_value)(struct udevice *dev, unsigned offset, int value);
    int (*get_function)(struct udevice *dev, unsigned offset);
        /* 这里具体看注释 */
    int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
             struct fdtdec_phandle_args *args);
};

  Note:函数都是以udevice和bank内的偏移为参数,驱动中根据udevice获取到对应bank的信息以及私有数据,然后根据偏移就可以确认是哪个GPIO。

3.gpio uclass driver

  DM模型中gpio模块的uclass。定义模块加载前和加载后的操作函数等等。

UCLASS_DRIVER(gpio) = {
    .id     = UCLASS_GPIO,
    .name       = "gpio",
    .flags      = DM_UC_FLAG_SEQ_ALIAS,
    .post_probe = gpio_post_probe,
    .post_bind = gpio_post_bind,
    .pre_remove = gpio_pre_remove,
    .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
};

4.gpio core

  DM框架下的接口

  • gpio_request_by_name
    int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, struct gpio_desc *desc, int flags)
    通过对应的udevice找到其dtsi节点中属性名为list_name的GPIO属性并转化 gpio_desc,并且request。
  • gpio_request_by_name_nodev
    int gpio_request_by_name_nodev(const void *blob, int node, const char *list_name, int index, struct gpio_desc *desc, int flags)
    通过对应的dtsi节点中属性名为list_name的GPIO属性并转化为gpio_desc,并且request。
  • dm_gpio_request
    int dm_gpio_request(struct gpio_desc *desc, const char *label)
    申请gpio_desc描述的GPIO
  • dm_gpio_get_value
    int dm_gpio_get_value(const struct gpio_desc *desc)
    获取gpio_desc描述的GPIO的值
  • dm_gpio_set_value
    int dm_gpio_set_value(const struct gpio_desc *desc, int value)
    设置gpio_desc描述的GPIO的值
  • dm_gpio_set_dir_flags
    int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
    设置gpio_desc描述的GPIO的输入输出方向,带标志
  • dm_gpio_set_dir
    int dm_gpio_set_dir(struct gpio_desc *desc)
    设置gpio_desc描述的GPIO的输入输出方向
  • dm_gpio_is_valid
    static inline bool dm_gpio_is_valid(const struct gpio_desc *desc)
    判断gpio_desc是否可用

  老接口:
  这些接口是为了兼容老版本的接口,注意,但是最终还是会调用DM框架下的接口

  • gpio_request
    int gpio_request(unsigned gpio, const char *label)
    申请一个GPIO
  • gpio_direction_input
    int gpio_direction_input(unsigned gpio)
    设置某个GPIO为输入
  • gpio_direction_output
    int gpio_direction_output(unsigned gpio, int value)
    设置某个GPIO为输出
  • gpio_get_value
    int gpio_get_value(unsigned gpio)
    获取某个GPIO上的值
  • gpio_set_value
    int gpio_set_value(unsigned gpio, int value)
    设置GPIO的值

5.关系图
在这里插入图片描述

6.U-boot Configuration

  To enable GPIO in u-boot, the following configurations need to be enabled.

CONFIG_DM=y
CONFIG_DM_GPIO=y
CONFIG_XXX_GPIO=y   //xxx:own soc 

7.Debug the gpio

  It contains code handling the “gpio” command in U-Boot’s shell.

cmd/gpio.c:
U_BOOT_CMD(gpio, 3, 0, do_gpio,
  "input/set/clear/toggle gpio pins",
  "<input|set|clear|toggle> <pin>\n"
  "    - input/set/clear/toggle the specified pin");

Enable GPIO command:

CONFIG_CMD_GPIO=y   //use the gpio command for debug

命令:

  • gpio set [pin] : 设置gpio输出高电平
  • gpio clear [pin]:设置gpio输出低电平
  • gpio toggle [pin]:切换gpio高低电平
  • gpio status -a :查看所有gpio状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值