增加 Pinctrl 和 sh-pfc 子系统.

Signed-off-by: rick.chan <chenyang@autoai.com>
This commit is contained in:
rick.chan 2020-08-07 12:01:55 +08:00
parent 7002fe3ac7
commit f7d6acc1ba
1 changed files with 55 additions and 0 deletions

View File

@ -0,0 +1,55 @@
# Pinctrl 和 sh-pfc 子系统
## 1.基本概念
### 1.1.Pin 与 GPIO 的差别
SOC 与其他外部设备通过 Pin 进行相互连接,某些 Pin 是 GPIO 功能,某些 Pin 是 SPI 功能,更多的 Pin 则复用了 GPIO 和其他功能,另外某些 Pin 属于 Power Supply 或 Clock Input。总之Pin 泛指 SOC 的各个硬件管脚,而 GPIO 是功能概念,专指那些具备 GPIO 功能的 Pin因此 GPIO 是 Pin 的一个子集。
### 1.2.Pinctrl 的实际需求
早期的 Linux 系统中没有 Pinctrl 的概念每个驱动自己设置自己的管脚Pin。这似乎是一个非常简单的好办法但问题是 Linux 要适应不同的平台。即便使用统一款 SOC相似的外围器件实际的硬件电路也可能不同。在一个项目里使用了 SPI1 去访问 SPI-Flash在另一个项目里可能用的却是 SP3。这个时候驱动工程师就要深入到各个驱动里去逐个修改Linux 有众多的驱动,一旦修改的地方不只一两处,开发人员就会深陷泥沼。有的时候驱动不正常,可能只是因为忘记了修改某个 Pin 的功能。
因此开发人员最好将 Pin 进行统一管理,一个 Pin 是用作 GPIO 还是 SPI或者其他第二功能应该由一个统一的系统来管理。将 Pin 作为统一的资源进行管理,也避免了使用上产生冲突的可能性,一旦某个 Pin 用作 I2C 了,那用户就不能再申请作为 GPIO 使用,除非前者释放了该资源。
因此诞生了 Pinctrl 子系统。Pinctrl 与 DeviceTree 配合工作,在 DeviceTree 中指定 Pin 所使用的功能Pinctrl 解析设备树,对管脚进行配置,这样以来,当硬件发生变化后,就不再需要修改代码,只要修改 DeviceTree 就可以了。这样,不同的硬件都可以使用同一个内核,只要启动时传入正确的 DeviceTree 就可以了。
对于 Pin 的第二功能,往往不是独立工作的,对于 SPI至少要有三个 Pin 配合工作CLK、MISO 和 MOSI这三个 Pin 应该一起被配置所以Pinctrl 提出了 Group 的概念,将具有同一功能的 Pin 组织到一起,统一配置和使用。
当今的 SOC 中,一个 Pin 往往不只具备两个功能甚至可以附加第三个、第四个功能。Pin 的不同功能,由 Function 来指定。另外 Pin 可以有不同的 State例如系统空闲、休眠时会将 Pin 设置为不同的状态。
### 1.3.Pinctrl 是如何解决现实问题的
由于大部分驱动模块都依赖于 Pinctrl因此Pinctrl 要先于其他驱动运行。Pinctrl 要对各个 Pin 进行配置,那么,何时才是配置 Pin 功能的最佳时机呢?在 Pinctrl 运行时就按照 DeviceTree 将所有 Pin 都配置一遍?
其实这是没必要的,如果 DeviceTree 中没有某个设备,也不必非得将对应的 Pin 设置为第二功能。Pinctrl 会在系统真正探测到某个设备时,触发将对应的 Pin 设置为正确的状态和功能。具体而言是在 really_probe 函数中调用的 pinctrl_bind_pins 方法。
```cpp
static int really_probe(struct device *dev, struct device_driver *drv)
{
...
...
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
if (ret)
goto pinctrl_bind_failed;
...
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
...
pinctrl_init_done(dev);
...
return ret;
}
```
## 2.sh-pfc
sh-pfc 是 Pinctrl 的一个子集Pinctrl 提供了许多回调函数,如果对应的是 sh-pfc 设备,则继续回调 sh-pfc 驱动的相关回调函数继续执行。sh-pfc 对 Pinctrl 进行了进一步的封装,使其更容易使用。