前言
參考文件:
- 核心文件連結:https://www.kernel.org/doc/Documentation/
- 核心原始碼doc:Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
建議配合 GPIO 子系統使用。
建議,複製 原文連結觀看,排版清晰,便於學習:
10. pinctrl子系統
pinctrl子系統 用於引腳的配置。如複用為那種引腳,電器特性等等。
gpio子系統 用於引腳的控制。如配置輸出,輸出高低電平等等。
當pinctrl子系統配置引腳為GPIO模式後,才能用gpio子系統控制引腳。
(pinctrl子系統可以把引腳配置為 GPIO模式,I2C模式* 等等*)
10.1 參考路徑
pinctrl子系統核心文件:Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
pinctrl子系統原始碼路徑:drivers/pinctrl
10.2 pinctrl子系統主要工作
pinctrl子系統 主要工作內容(核心實現):
- 獲取裝置樹中使用者配置的 PIN 資訊。
- 根據獲取到的資訊,配置 PIN 的複用功能、電氣特性。
以上工作內容都是核心實現的,使用者不需要自己編寫程式碼,只需要配置好裝置樹即可。
10.2 pinctrl子系統格式說明
pin controller 子節點格式是由晶片廠商自定義的,即每家晶片pin controller子節點格式都是不一樣的。
各個廠商的 pinctrl 使用說明可以參考廠商提供的文件或去核心原始碼路徑 Documentation/devicetree/bindings/pinctrl 目錄下找到對應廠商的使用說明。
格式規範如:
imx6ull格式:
//client端:
@節點名字 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_自定義名字A>;
status = "okay";
};
//pincontroller服務端
pinctrl_自定義名字A: 自定義名字B {
fsl,pins = <
引腳複用巨集定義 PAD(引腳)屬性, // 引腳 A
引腳複用巨集定義 PAD(引腳)屬性; // 引腳 B
>;
};
rk3288例項:
//client端
@uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; //它使用三個節點來表示三組引腳。
status = "okay";
};
//pincontroller服務端
gpio4_uart0 {
// 引腳 A
uart0_xfer: uart0-xfer {
rockchip,pins = <UART0BT_SIN>, <UART0BT_SOUT>; //使用rockchip,pins來指定使用哪些引腳,就等效於groups
rockchip,pull = <VALUE_PULL_DISABLE>; //引腳的引數
rockchip,drive = <VALUE_DRV_DEFAULT>; //引腳的引數
};
// 引腳 B
uart0_cts: uart0-cts {
rockchip,pins = <UART0BT_CTSN>;
rockchip,pull = <VALUE_PULL_DISABLE>;
rockchip,drive = <VALUE_DRV_DEFAULT>;
};
// 引腳 C
uart0_rts: uart0-rts {
rockchip,pins = <UART0BT_RTSN>;
rockchip,pull = <VALUE_PULL_DISABLE>;
rockchip,drive = <VALUE_DRV_DEFAULT>;
};
uart0_rts_gpio: uart0-rts-gpio {
rockchip,pins = <FUNC_TO_GPIO(UART0BT_RTSN)>;
rockchip,drive = <VALUE_DRV_DEFAULT>;
};
};
10.3 概念
上面例子中說到 pin controller 和 client device,這兩個節點說明都在檔案 pinctrl-bindings.txt 中有說明。
pin controller:
- 服務端。
- 提供引腳的配置資訊。
client device:
- 客戶端。
- 宣告需要使用哪個引腳。(使用來自客戶端提供的引腳資訊)
- 客戶端其實就是需要使用該引腳的裝置樹節點。
/* For a client device requiring named states */
device {
pinctrl-names = "active", "idle"; // 該裝置有兩種狀態,分別對應 pinctrl-0 和 pinctrl-1
pinctrl-0 = <&state_0_node_a>; // 第 0 個狀態的名字為 active。對應的引腳在 pinctrl-0 裡。
pinctrl-1 = <&state_1_node_a &state_1_node_b>; // 第 1 個狀態的名字為 idle。對應的引腳在 pinctrl-1 裡。
};
function:
- 功能。
groups:
- 使用 function 功能的 N 組引腳。
如:
state_0_node_a
{
uart0
{
function = "uart0";
groups = "u0rxtx", "u0rtscts";
};
};
10.4 例項分析
以 IMX6UL 為例子分析。
參考 NXP 提供的關於 pinctrl 文件或去 Documentation/devicetree/bindings/pinctrl 下找到文件 fsl,imx6ul-pinctrl.txt 和 fsl,imx-pinctrl.txt。
工具相應文件編寫 pinctrl 配置資訊。
根據文件得出以下幾點關於 IMX6ULL pinctrl 子系統開發的要求:
- 節點 iomux 彙總所需引腳的配置資訊。即是 pinctrl 子系統儲存使用著 iomux 節點資訊。
- 要在特定功能上工作的 pin ,應該在該特定功能節點下定義。
- 驅動程式可以使用客戶節點的名稱和服務節點的名稱來描述引腳功能和組層次結構。
- 例如,Linux IMX pinctrl驅動程式以客戶節點的名稱作為函式名,服務節點的名稱作為組名來建立對映表。
- 每個管腳配置節點都應該有一個phandle(即是pinctrl-0),裝置可以通過引用該管腳配置節點的phandle 來設定管腳配置。
10.4.1 pin controller服務端
有些SoC 把 PIN 叫 PAD
格式有晶片廠商定義
引腳複用巨集 & 引腳屬性值:
引腳複用巨集定義 如 MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 在 核心原始碼/arch/arm/boot/dts/imx6ul-pinfunc.h 檔案中定義,由晶片廠商編寫。
如圖:
-
引腳複用巨集 由5個引數組成,分別為:
- mux_reg:複用選擇暫存器的偏移地址。
- conf_reg:引腳屬性控制的偏移地址。
- input_reg:輸入選擇暫存器偏移地址。(用於輸入的引腳)
- mux_mode:複用選擇暫存器模式選擇位的值。
- input_val:輸入選擇暫存器的值。
前面三個均為 暫存器地址偏移值,後面兩個為對應要寫入暫存器的值。
對應規則:
- mux_reg <-- mux_mode
- conf_reg <-- 引腳屬性值 (巨集後面的引數)
- 因為引腳屬性配置比較多樣靈活,所以由使用者決定該值,便提出到巨集外。
- input_reg <-- input_val
10.4.2 client device客戶端
格式規範由裝置樹規定
客戶端其實就是需要使用該引腳的裝置樹節點。
客戶端必須至少有一個 pinctrl-0 狀態。