리눅스 커널을 오랜만에 살펴보려니 디바이스 트리(DeviceTree)가 은근히 헷갈린다.
그래서 혼자 공부할겸, pinctrl 문서를 변역하면서 살펴 보았다. pinctrl을 사용해서 kernel driver 초기화 시에 사용할 pin들을 제어해 보자.
pinctrl은 linux kernel device tree에서 gpio pin을 구성하기 위해 사용한다.
== 소개 ==
핀 다중화(pin multiplexing)를 control하거나 pull-up/pull-down, tri-state, drive-strength 등과 같은 구성 매개변수(configuration parameters) 를 제어하는 하드웨어 모듈은 핀 컨트롤러(pin controller)로 지정됩니다. 각각의 핀 컨트롤러는 다른 하드웨어 모듈과 마찬가지로 device tree에서 node로 표시되어야 합니다.
Signal이 핀 구성의 영향을 받는 하드웨어 모듈은 클라이언트 장치(Client devices)로 지정됩니다. 다시 한번 말하지만, 각 클라이언트 장치는 다른 하드웨어 모듈과 마찬가지로 device tree의 node로 표시되어야 합니다.
클라이언트 장치(client device)가 올바르게 작동하려면 특정 핀 컨트롤러가 특정 핀 구성을 설정해야 합니다.
일부 클라이언트 장치에는 예를 들면 초기화 중의 설정(setup) 같은 단일 고정 핀 구성(single static pin configuration)이 필요합니다. 다른 것들은 런타임 시 핀을 재구성해야 합니다. (예를 들어 장치가 비활성(inactive) 상태일 때 3상태 핀(tri-state pins)으로 구성하는 등의 )
따라서 각 클라이언트 장치는 일련의 이름을 정의한 상태 집합으로 정의할 수 있습니다. 이런 상태의 number와 name은 클라이언트 장치의 자체 바인딩(own binding)에 의해 정의됩니다.
이 파일에 정의된 공통 pinctrl binding은 상태 이름을 해당 상태에서 사용되는 핀 구성에 매핑하기 위해서 클라이언트 device tree node에 대한 인프라를 제공합니다.
핀 컨트롤러 자체가 자체 클라이언트 장치일 수도 있습니다.
예를 들어, 핀 컨트롤러는 드라이버가 로드될 때 자체 "active" 상태를 설정할 수 있습니다. 이렇게 하면 여러 클라이언트 장치 노드에 분할하지 않고 보드의 고정 핀 구성을 한 곳에서 나타낼 수 있습니다. 이 작업을 수행할지 여부에 대한 결정은 개별 board device tree 파일의 작성자와 해당 보드에서 사용 중인 개별 클라이언트 장치에 대한 바인딩에 의해 부과된 요구 사항, 즉 dynamic pin configuration을 위해 특정 명명된 상태가 필요한지 여부에 달려 있습니다.
== Pinctrl 클라이언트 장치 ==
각 클라이언트 장치에 대해 개별적으로 모든 핀 상태에 숫자 ID가 할당됩니다. 이 숫자는 0에서 시작하며 연속적입니다. 각 상태 ID에는 핀 구성을 정의하는 고유한 속성이 있습니다. 각각의 상태에는 이름이 할당될 수도 있습니다. 이름이 사용되면 해당 이름에서 정수 ID로 매핑되는 다른 속성이 있습니다.
각 클라이언트 장치의 고유한 binding은
device tree node에 정의해야 하는 상태 집합과 제공해야 하는 상태 ID 집합을 정의할지 여부 또는 제공해야 하는 상태 이름 집합을 정의할지 여부를 결정합니다.
필수 속성:
pinctrl-0:
각각 핀 구성 노드를 가리키는 phandle의 목록입니다. 이러한 참조된 핀 구성 노드는 구성하는 핀 컨트롤러의 자식 노드여야 합니다. 이 목록에 여러 항목이 있을 수 있으므로 여러 핀 컨트롤러를 구성하거나 단일 핀 컨트롤러에 대해 여러 노드에서 상태를 구축할 수 있습니다. 각 노드는 전체 구성에 기여합니다. 이러한 핀 구성 노드의 형식에 대한 자세한 내용은 이 문서의 다음 섹션을 참조하십시오.
어떤 경우에는 상태를 정의하는 것이 유용할 수 있지만, 비어 있어야 하는 경우도 있습니다. 이것은 핀 컨트롤러가 없거나 핀 컨트롤러가 해당 HW 모듈에 영향을 미치지 않는 SoC에서 공통 IP 블록을 사용할 때 필요할 수 있습니다. 해당 IP 블록에 대한 바인딩에서 특정 핀 상태가 존재해야 하는 경우 해당 핀 상태를 정의해야 하지만 비워 둘 수도 있습니다.
선택적 속성:
pinctrl-1:
각각 핀 컨트롤러 내의 pin configuration node를 가리키는phandles의 list 입니다.
...
pinctrl-n:
각각 핀 컨트롤러 내의 pin configuration node를 가리키는phandles의 list 입니다.
pinctrl-names:
상태를 할당할 name List입니다. List 항목 0은 정수 상태 ID 0의 이름을 정의하고, List 항목 1은 상태 ID 1을 정의합니다.
예를 들면
/* For a client device requiring named states */
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/* For the same device if using state IDs */
device {
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/*
* For an IP block whose binding supports pin configuration,
* but in use on an SoC that doesn't have any pin control hardware
*/
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <>;
pinctrl-1 = <>;
};
/*
* 바인딩이 핀 구성을 지원하지만 핀 제어 하드웨어가 없는 SoC에서 사용 중인 IP 블록의 경우.
* or an IP block whose binding supports pin configuration, but in use on an SoC that doesn't have any pin control hardware */
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <>;
pinctrl-1 = <>;
};
Documentation/devicetree/bindings/pinctrl/pinctrl.yaml
== 핀 컨트롤러 장치 ==
필수 properties: 핀 컨트롤러 드라이버 관련 문서 참조
선택적 속성:
#pinctrl-cells:
핀 컨트롤러 장치 인스턴스 내의 index 로 추가되는 핀 컨트롤 셀의 수
핀 컨트롤러 장치는 클라이언트 장치가 참조하는 핀 구성 노드를 포함해야 합니다.
예를 들어:
pincontroller {
... /* Standard DT properties for the device itself elided */
state_0_node_a {
...
};
state_1_node_a {
...
};
state_1_node_b {
...
};
}
각 핀 구성 자식 노드의 내용은 개별 핀 컨트롤러 장치에 대한 바인딩에 의해 정의됩니다. 이 콘텐츠에 대한 공통 표준은 없습니다. pinctrl 프레임워크는 핀 컨트롤러 드라이버가 사용할 수 있는 일반 도우미 바인딩만 제공합니다.
핀 구성 nodes는 핀 컨트롤러 장치의 직접적인 자식일 필요는 없습니다. 예를 들어, 그들은 손자일 수 있습니다. 이것이 규칙에 맞는지 여부와 자식 노드와 중간 부모 노드 사이에 상호 작용이 있는지 여부는 개별 핀 컨트롤러 장치에 대한 바인딩에 의해 완전히 재정의됩니다.
== 일반 핀 다중화 노드 내용 ==
핀 다중화 노드: pin multiplexing nodes
function : 선택할 mux function
groups : 이 기능으로 선택할 그룹 목록 (this 또는 "pins"중 하나를 지정해야 합니다.)
pins : 이 기능으로 선택할 핀 목록(this 또는 ""groups"이 지정되어야 함)
예시:
state_0_node_a {
uart0 {
function = "uart0";
groups = "u0rxtx", "u0rtscts";
};
};
state_1_node_a {
spi0 {
function = "spi0";
groups = "spi0pins";
};
};
state_2_node_a {
function = "i2c0";
pins= "mfio29", "mfio30";
};
핀 컨트롤러 하드웨어에 따라 더 적합한 경우 선택적으로 대체 바인딩을 사용할 수 있습니다.
동일한 핀 컨트롤러 인스턴스가 많은 하드웨어의 경우 각 pin과 function의 이름을 지정하는 것은 쉽게 유지 관리할 수 없게 될 수 있습니다. 이는 SoC 개정 및 패키징에 따라 동일한 컨트롤러가 다른 핀과 기능에 사용되는 경우 특히 그렇습니다.
이와 같은 경우 핀 컨트롤러 드라이버는 하드웨어 기반 인덱스 및 여러 핀 구성 값과 함께 pinctrl-pin-array 도우미 바인딩을 사용할 수 있습니다.
pincontroller {
... /* 장치 자체에 대한 표준 DT 속성이 생략됨 */
#pinctrl-cells = <2>;
state_0_node_a {
pinctrl-pin-array = <
0 A_DELAY_PS(0) G_DELAY_PS(120)
4 A_DELAY_PS(0) G_DELAY_PS(360)
...
>;
};
...
};
위의 #pinctrl-cells는 레지스터 인덱스 외에 값 셀의 수를 지정합니다. 이것은 한 가지 예외를 제외하고 인터럽트 확장 바인딩과 유사합니다. 정의된 핀은 항상 핀 컨트롤러 노드의 자식이므로 각 항목에 대해 phandle을 지정할 필요가 없습니다. 또한 pinctrl 프레임워크가 각 핀 제어 장치에 대해 핀을 그룹화하기 위해 명명된 모드를 사용하기 때문에 phandle이 다른 핀 컨트롤러를 가리키도록 하는 것은 현재 작동하지 않습니다.
pinctrl-pin-array에 대한 인덱스는 pinctrl 레지스터에 대한 하드웨어와 관련되어야 하며 핀 인스턴스의 가상 인덱스가 아니어야 합니다. 그 이유는 dts 파일의 인덱스와 핀 컨트롤러 드라이버가 변경될 수 있으므로 매핑을 피하기 위함입니다.
각 단일 핀에 대해 핀 다중화 구성을 지정해야 하는 하드웨어의 경우 "pin" 및 "function" 속성을 포함하는 필수 하위 노드의 수가 빠르게 증가하고 작성 및 유지 관리가 어려워질 수 있습니다.
이와 같은 경우 핀 컨트롤러 드라이버는 pinmux 그룹의 mux 구성 설정과 함께 핀 식별자가 제공되는 pinmux 도우미 속성을 사용할 수 있습니다. pinmux 그룹은 단일 정수 또는 정수 배열로 표시되는 핀 식별자와 mux 설정으로 구성됩니다.
pinmux 속성은 각각 단일 핀 다중화 구성을 설명하는 pinmux 그룹의 배열을 허용합니다.
pincontroller {
state_0_node_a {
pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
};
};
각 개별 핀 컨트롤러 드라이버 바인딩 문서는 핀 ID와 핀 다중화 구성이 어떻게 정의되고 pinmux 그룹에서 함께 조합되는지 지정해야 합니다.
== 일반 핀 구성 노드 내용 ==
핀 구성 노드에 표시되는 많은 데이터 항목은 공통적이고 일반적입니다. 핀 제어 바인딩은 적용 가능한 경우 아래에 정의된 속성을 사용해야 합니다. 이러한 모든 속성이 모든 하드웨어 또는 바인딩 구조에 관련되거나 유용한 것은 아닙니다. 각 개별 바인딩 문서는 이러한 일반 속성(있는 경우)과 이러한 속성을 포함하는 DT 노드의 구조를 명시해야 합니다.
지원되는 일반 속성은 다음과 같습니다.
pins - 노드의 속성이 적용되는 핀 목록("group" 또는 "pinmux"가 지정되어야 함)
group - 드라이버가 개별 핀이 아닌 전체 그룹의 구성을 지원하는 경우 속성을 적용할 그룹
(여기서 "pins" 또는 "pinmux"를 지정해야 함)
pinmux - 노드의 속성이 적용되는 숫자 핀 ID 및 해당 mux 설정 목록("핀" 또는 "그룹"이 지정되어야 함)
bias-disable - 모든 핀 바이어스 비활성화
bias-high-impedance - 고 임피던스 모드("제3 상태", "플로팅")
bias-bus-hold - 약하게 래치
bias-pull-up - pull up the pin
bias-pull-down - pull down the pin
bias-pull-pin-default - 핀 기본 풀 상태 사용
drive-push-pull - 능동적으로 높고 낮게 드라이브
drive-open-drain - drive with open drain
drive-open-source - 오픈 소스로 드라이브
drive-strength - 최대 XmA의 싱크 또는 소스
input-enable - 핀에서 입력 활성화(입력 버퍼 활성화와 같이 출력에 영향 없음)
input-disable - 핀의 입력 비활성화(입력 버퍼 비활성화와 같은 출력에 영향 없음)
input-schmitt-enable - 슈미트 트리거 모드 활성화
input-schmitt-disable - 슈미트 트리거 모드 비활성화
input-debounce - 디바운스 시간 X가 있는 디바운스 모드
power-source - 다른 전원 공급 장치 중에서 선택
low-power-enable - 저전력 모드 활성화
low-power-disable - 저전력 모드 비활성화
output-disable - 핀의 출력 비활성화(예: 출력 버퍼 비활성화)
output-enable - 능동적으로 구동하지 않고 핀의 출력을 활성화합니다.
(예: 출력 버퍼 활성화)
output-low - 핀을 로우 레벨로 출력 모드로 설정
output-high - 핀을 하이 레벨로 출력 모드로 설정
sleep-hardware-state - 이것이 슬립 상태에 대한 레지스터에 프로그래밍될 슬립 관련 상태임을 나타냅니다.
slew-rate - 슬루율을 설정합니다.
예를 들어:
state_0_node_a {
cts_rxd {
pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
bias-pull-up;
};
};
state_1_node_a {
rts_txd {
pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
output-high;
};
};
state_2_node_a {
foo {
group = "foo-group";
bias-pull-up;
};
};
state_3_node_a {
mux {
pinmux = <GPIOx_PINm_MUXn>, <GPIOx_PINj_MUXk)>;
input-enable;
};
};
일부 일반 속성은 인수를 사용합니다. 이 경우에 대한, 인수들은 아래에 설명되어 있습니다.
- 핀은 핀 이름 또는 ID 목록을 필수 인수로 사용합니다.
하드웨어에 대한 특정 바인딩은 다음을 정의합니다.
- 항목이 정수인지 문자열인지 여부와 그 의미.
- pinmux는 핀 ID 및 mux 설정 목록을 필수 인수로 사용합니다.
하드웨어에 대한 특정 바인딩은 다음을 정의합니다.
- 핀 ID 및 mux 설정이 단일 정수 또는 정수 배열로 함께 정의되고 조합되는 방법.
- bias-pull-up, -down 및 -pin-default는 옴 단위의 풀 강도를 지원하는 하드웨어에서 선택적 인수로 사용됩니다. bias-disable은 풀을 비활성화합니다.
- 구동 강도는 목표 강도(mA)를 인수로 사용합니다.
- input-debounce는 usec의 디바운스 시간을 인수로 사용하거나 0을 사용하여 디바운싱을 비활성화합니다.
이 매개변수에 대한 더 자세한 문서는 <include/linux/pinctrl/pinconf-generic.h>에서 찾을 수 있습니다.
'임베디드' 카테고리의 다른 글
JTAG과 SWD의 차이와 장단점 (0) | 2023.10.18 |
---|---|
가속도계(Accelerometer)와 방향 계산 (0) | 2023.09.08 |
Linux CAN Network - CAN드라이버와 SocketCAN (0) | 2022.11.05 |
regmap_update_bits 함수 (0) | 2022.10.28 |
댓글