关键流程设计
pin 脚功能定义
在 pinctrl 子系统中,有 function 和 group 的概念。function 是指某个具体的功能,如 uart0、spi1、i2c2 等。soc 的几个 pin 脚可以构成一个 group,形成特定的功能,如 PA0 和 PA1 可以组成 uart0。一个 function 往往包含一个或多个 group,例如,uart0 这个 function 可以由 PA0 和 PA1 组成,也可以由 PA2 和 PA3 组成。pinctrl 子系统就是通过 function 和 group 来确定最终需要设置的 pin 脚。
PINCTRL 模块的驱动定义了一个结构体数组,存储每个 pin 脚的所有可复用功能。如下所示,PA0 是该 pin 脚的名称,下面依次是 PA0 可实现的功能复用。AIC_FUNCTION(index, func_name)用来定义 pin 脚功能复用时所对应的索引值。即 PA0 作为 GPIOA0 时,是使用的 function 1。作为 uart0 时,是使用的 function 5。驱动中并不会区分该 pin 脚是 uart0 的 RX 还是 TX 这些细节。
static struct aic_desc_pin aic_pins_v1[] = {
AIC_PIN(
PINCTRL_PIN(0, "PA0"),
AIC_FUNCTION(1, "GPIOA0"),
AIC_FUNCTION(2, "GPAI0"),
AIC_FUNCTION(3, "jtag"),
AIC_FUNCTION(5, "uart0")
),
AIC_PIN(
PINCTRL_PIN(1, "PA1"),
AIC_FUNCTION(1, "GPIOA1"),
AIC_FUNCTION(2, "GPAI1"),
AIC_FUNCTION(3, "jtag"),
AIC_FUNCTION(5, "uart0")
),
/* 此处省略其它pin脚配置 */
}
在 pinctrl 子系统中,一个 group 一般会包含多个 pin 脚。而在 PINCTRL 模块实现的驱动中,是将每个 pin 脚都看作一个 group,这样做的优点是:
-
不需要再单独定义每个 group 的 pin 脚组成情况,
-
不需要再定义 function 与 group 的对应关系
-
驱动源码简单明了,由上面的数组可以快速直观的了解到每个 pin 脚可复用的功能
按照 pinctrl 子系统对 function 和 group 的定义,gpio 模块的 uart0 包含 2 个 group,每个 group 包含 2 个 pin 脚,通过 uart0 可以找到这 4 个 pin 脚。而按照 gpio 模块实现的驱动,uart0 包含 4 个 group,每个 group 包含 1 个 pin 脚,最终通过 uart0 也可以找到 4 个 pin 脚。
初始化流程
-
释放 reset 和 clock
-
调用 state,构建 function 与 group 的关系
-
初始化 pinctrl 结构体变量
-
注册 controller 设备
-
调用 bank,注册各个 gpio bank
-
初始化完成
设备 pinmux 配置流程
在各个外设的驱动中,并没有调用与 pin 脚复用相关的接口,那么各个外设的 pin 脚复用功能是什么时候生效的呢?pin 脚复用功能是如何进行初始化的?了解这个过程,有助于加深对 pinctrl 子系统的了解。外设的 pin 脚复用初始化流程如下: