7.2 GPIO子系统的数据结构

GPIO 子系统层次结构

GPIO 子系统可分为3层,分别是使用者、抽象层、控制器驱动:

  1. 使用者:即使用 GPIO子系统的驱动,它们使用抽象层向上提供的接口
  2. 抽象层:启承上启下作用,向上为使用者提供统一接口,向下提供管理多个 GPIO 控制器驱动的功能
  3. 控制器驱动:用于驱动 GPIO 控制器,它按照抽象层的要求实现相应得到的硬件控制

gpio_devic 对象

gpio_devic 对象表示一个 GPIO 控制器,其核心成员如下:

	//ID ,表示是系统中的第几个 GPIO 控制器,由系统自动分配
	int id;
	//提供 GPIO 操作函数集合及一些创建 gpio_devic 所需的基本消息
	struct gpio_chip *chip;
	//用于描述 GPIO 的数组,每个 GPIO 都应该有一个结构体
	struct gpio_desc *descs;
	//GPIO 基值
	int base;
	//GPIO 个数
	u16 ngpio;
	//控制器名字
	const char *label;
	//gpio_pin_range 类型的链表,用于描述 GPIO 子系统中的 GPIO 编号与 pinctrl 控制器中的引脚编号的对应关系
	struct list_head pin_ranges;

gpio_chip 对象

gpio_chip 对象中包含操作 GPIO 的函数,其主要成员如下:

	//请求 GPIO
	int (*request)(struct gpio_chip *chip, unsigned offset);
	//释放 GPIO
	void (*free)(struct gpio_chip *chip, unsigned offset);
	//获取 IO 方向,0输出,1输入
	int (*get_direction)(struct gpio_chip *chip, unsigned offset);
	//设置为输入
	int (*direction_input)(struct gpio_chip *chip, unsigned offset);
	//设置为输出
	int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value);
	//获取 IO 状态
	int (*get)(struct gpio_chip *chip, unsigned offset);
	//设置 IO 状态
	void (*set)(struct gpio_chip *chip, unsigned offset, int value);
	//配置 GPIO。config参数参考enum pin_config_param
	int (*set_config)(struct gpio_chip *chip, unsigned offset, unsigned long config);
	//对 GPIO 的中断进行映射
	int (*to_irq)(struct gpio_chip *chip, unsigned offset);
	//GPIO 基值,为-1表示由系统分配
	int base;
	//GPIO 个数
	u16 ngpio;
	//控制器名字
	const char *label;
	//GPIO 控制器的设备树节点
	struct device_node *of_node;
	//访问 IO 时是否可能会执行引起休眠的函数,在通过 I2C 或 SPI 访问 GPIO 扩展芯片时必须为 true
	bool can_sleep;

gpio_desc 对象

gpio_desc 对象用于描述单个 GPIO ,其核心成员如下:

	//引脚属于哪个 GPIO 控制器
	struct gpio_device *gdev;
	//连接标签,可以用来描述当前功能,如驱动led、按键中断等
	const char *label;
	//GPIO 名字
	const char *name;

gpio_pin_range 对象

gpio_pin_range 对象用于描述 GPIO 子系统中的 GPIO 编号与 pinctrl 控制中的引脚编号之间的对应关系,其核心成员如下:

	//链表节点,用于在struct gpio_device中构成链表
	struct list_head node;
	//GPIO控制器所关联的 pinctrl_dev
	struct pinctrl_dev *pctldev;
	//引脚映射关系
	struct pinctrl_gpio_range range;
	
	/* pinctrl_gpio_range 展开后的核心成员如下 */
	//链表节点,用于在struct pinctrl_dev构成链表
	struct list_head node;
	//名称
	const char *name;
	//ID 号
	unsigned int id;
	//GPIO 控制器中的 GPIO 编号
	unsigned int base;
	//对应的 pinctrl 控制器中的引脚编号
	unsigned int pin_base;
	//引脚数量
	unsigned int npins;
	//所对应的 gpio_chip
	struct gpio_chip *gc;

pinctrl 子系统与 GPIO 子系统的关系

在 struct pinctrl_dev 中有一个成员 struct list_head gpio_ranges ,它是一个链表,其中包含一系列的 struct pinctrl_gpio_range 对象(struct pinctrl_dev中的gpio_ranges 链表与struct gpio_device中的struct list_head pin_ranges链表都包含有一个相同的struct pinctrl_gpio_range对象,只不过struct gpio_device是通过gpio_pin_range对象来间接包含的),用于描述 GPIO 控制器中的 GPIO 编号与 pinctrl 控制器中的引脚编号之间的对应关系。
在驱动开发中可通过在 GPIO 控制器的设备树节点中添加 gpio-ranges 属性将 pinctrl 子系统与 GPIO 子系统关联到一起,gpio-ranges属性的格式如下:

gpio-ranges = <引用关联的 pinctrl 节点  GPIO 控制器的 GPIO 编号  GPIO 编号对应的 pinctrl 引脚号  引脚数>;
如 gpio-ranges = <&pinctrl 0 32 16> 表示此 GPIO 控制器的0号引脚对应 pinctrl 控制器的32号引脚,总共映射16个引脚

如果设备树没有提供 gpio-ranges 属性还可以通过 gpiochip_add_pin_range 等函数进行关联(实际上设备树增加gpio-ranges属性后,在注册GPIO控制器过程中便会自动会调用gpiochip_add_pin_range 函数)。
将 GPIO 子系统与 pinctrl 子系统关联后 GPIO 子系统也不能自动调用 pinctrl 子系统将引脚配置为 GPIO 模式,还需要实现如下函数:
在 GPIO 子系

  1. 在设备树中提供 gpio-ranges 属性,或者在注册后调用gpiochip_add_pin_range函数
  2. 在 GPIO 控制器驱动实现 request 函数,这个函数需要调用 gpiochip_generic_request 函数
  3. 在 GPIO 控制器驱动实现 free 函数,这个函数需要调用 gpiochip_generic_free 函数
  4. 在 pinctrl 控制器驱动的 pinmux_ops 中实现 gpio_request_enable 或 request 函数,用于将引脚配置为 GPIO 功能
  5. 在 pinctrl 控制器驱动的 pinmux_ops 中实现 gpio_disable_free 或 free 函数,用于实现第 3 步的反操作 [可选]

stm32 的 pinctrl 子系统与 GPIO 子系统关联方法

在STM32的驱动中采用了另外一种办法来关联GPIO控制器驱动和pinctrl 控制器驱动:

  1. 在设备树中提供 gpio-ranges 属性
  2. 在 GPIO 控制器驱动中实现 request 函数,并调用了 pinctrl_gpio_request 函数(gpiochip_generic_request 也是采用此函数实现)
  3. 在 GPIO 子系统的 direction_input 和 direction_output 中调用了 pinctrl_gpio_direction_input 和 pinctrl_gpio_direction_output 函数来将引脚配置为 GPIO 模式并设置方向(pinctrl_gpio_direction_input和pinctrl_gpio_direction_output 最终会调用到 pinctrl 控制器驱动 pinmux_ops 中的 gpio_set_direction 函数)
    NOTE:在 STM32 的驱动中没有为 pinctrl 的 pinmux_ops 提供 gpio_request_enable 和 request 函数,导致在 GPIO
    子系统中 request 函数不能将引脚配置为 GPIO 模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值