4. 표준 프로퍼티 레퍼런스
4.1 표준 프로퍼티 레퍼런스
디바이스 트리(Device Tree)에서 모든 노드가 공통으로 사용할 수 있거나, 특정 계층에서 약속된 의미를 갖는 표준 프로퍼티(Standard Properties)들이 있습니다. 커널은 이 프로퍼티들을 읽어 하드웨어 자원을 할당하고 드라이버를 매칭합니다.
📋 디바이스 트리 표준 프로퍼티 요약표
| 프로퍼티 | 타입 | 설명 | 예시 |
| compatible | string-list | 드라이버 매칭 키. 구체적→일반적 순서 | "vendor,exact", "vendor,fallback" |
| reg | prop-encoded | 주소/크기 쌍. 해석은 부모의 #address-cells/#size-cells에 의존 | <0x10000 0x1000> |
| interrupts | prop-encoded | 인터럽트 지정자. 해석은 인터럽트 컨트롤러의 #interrupt-cells에 의존 | <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH> |
| interrupt-parent | phandle | 인터럽트 컨트롤러 참조 (생략 시 부모 노드에서 상속) | <&gic> |
| clocks | phandle+args | 클럭 소스 참조 | <&ccu CLK_UART0> |
| clock-names | string-list | 클럭 이름 (clocks와 순서 대응) | "apb", "mod" |
| resets | phandle+args | 리셋 컨트롤러 참조 | <&ccu RST_UART0> |
| status | string | "okay"=활성, "disabled"=비활성 | "okay" |
| #address-cells | u32 | 자식 reg의 주소 u32 개수 | <2> |
| #size-cells | u32 | 자식 reg의 크기 u32 개수 (0이면 크기 없음) | <1> |
| ranges | prop-encoded | 자식→부모 주소 변환. 빈 값이면 1:1 매핑 | <0x0 0x0 0x10000000 0x1000000> |
| dma-ranges | prop-encoded | DMA 주소 변환 (CPU 주소 ≠ DMA 주소일 때) | <0x0 0x0 0x80000000 0x80000000> |
| pinctrl-0 | phandle-list | 핀 설정 참조 (상태 0=default) | <&uart0_pins> |
| pinctrl-names | string-list | 핀 설정 상태 이름 | "default", "sleep" |
| *-gpios | phandle+args | GPIO 참조 (접두사가 이름) | reset-gpios = <&gpio1 5 GPIO_ACTIVE_LOW> |
| *-supply | phandle | 전원 레귤레이터 참조 | vcc-supply = <®_3v3> |
1. 장치 식별 및 매칭 관련
가장 기본이 되며, 커널이 어떤 드라이버를 호출할지 결정하는 프로퍼티들입니다.
- compatible: 장치의 이름을 정의합니다. "제조사,모델" 형식의 문자열 리스트이며, 가장 구체적인 이름부터 범용적인 이름 순으로 나열합니다. 커널은 이 문자열을 드라이버의 of_device_id 테이블과 대조하여 일치하는 드라이버를 로드합니다.
- model: 사용자가 읽기 위한 장치의 모델명을 기술합니다. (예: "Samsung Exynos5422 Chromebook 2")
- status: 장치의 작동 상태를 나타냅니다.
- "okay": 장치가 작동 중이며 사용 가능함.
- "disabled": 장치가 현재 사용 불가능함 (드라이버가 로드되지 않음).
2. 주소 및 자원 할당 관련
부모 노드가 자식 노드의 리소스 범위를 해석하는 방법을 정의합니다.
- reg: 장치의 물리적 주소 범위(Address)와 크기(Size)를 정의합니다. reg = <address1 size1 [address2 size2] ...>; 형태로 작성합니다.
- #address-cells: 자식 노드의 reg 내 주소 필드가 몇 개의 32비트 워드(cell)로 구성되는지 정의합니다.
- #size-cells: 자식 노드의 reg 내 크기 필드가 몇 개의 cell로 구성되는지 정의합니다.
- ranges: 자식 버스의 주소 공간을 부모 버스의 주소 공간으로 매핑하는 변환 표입니다. 값이 비어 있으면 부모와 자식의 주소 공간이 1:1로 일치함을 의미합니다.
3. 인터럽트 관련
장치가 발생시키는 이벤트를 CPU에 알리기 위한 설정입니다.
- interrupts: 장치가 사용하는 인터럽트 신호의 리스트입니다. (인터럽트 번호, 트리거 방식 등)
- interrupt-parent: 해당 장치의 인터럽트 신호를 처리하는 인터럽트 컨트롤러(GIC 등)를 phandle로 지정합니다.
- #interrupt-cells: 해당 인터럽트 컨트롤러가 인터럽트 신호를 해석할 때 필요한 cell의 개수를 정의합니다.
4. 기타 주요 프로퍼티
- device_type: 노드의 역할을 정의합니다. 예전에는 많이 쓰였으나 현재는 cpu나 memory 노드 등 특정 핵심 노드에서만 필수적으로 사용됩니다.
- phandle: 노드에 부여되는 고유한 숫자 ID입니다. 보통 사용자가 직접 입력하기보다 라벨(label:)을 붙이면 컴파일러(DTC)가 자동으로 생성하여 다른 노드에서 참조(<&label>)할 수 있게 합니다.
💡 실전 팁
- 새로운 장치를 추가할 때 compatible 작성 시에는 아무렇게나 짓지 않고, 커널 소스 내의 Documentation/devicetree/bindings/ 경로의 공식문서를 먼저 확인하여 표준에 맞게 이름을 작성하는 것이 원칙으로, 매우 중요합니다.
- status = "disabled"로 설정된 노드는 커널이 드라이버를 로드하지 않으므로, 하드웨어는 존재하지만 소프트웨어적으로 끄고 싶을 때 유용하게 사용됩니다.
4.2 드라이버 코드에서 property 가져오기
리눅스 커널 드라이버는 부팅 시 생성된 디바이스 트리 데이터(Device Tree Blob)를 파싱하여 자신의 하드웨어 정보를 가져옵니다. 이때 주로 사용하는 API가 of_property_read_... 계열의 함수들입니다.
리눅스 커널 드라이버(C 언어)가 어떻게 실제 데이터를 가져와서 하드웨어를 제어하는지, 그 과정을 핵심 단계별로 정리해 드릴게요.
커널은 of_ (Open Firmware) API 계열 함수들을 사용하여 디바이스 트리 노드에 접근합니다.
1. 드라이버와 DTS의 연결 고리 (Matching)
먼저 드라이버는 자신이 어떤 compatible 문자열을 지원하는지 선언해야 합니다.
커널은 DTS의 compatible 문자열과 드라이버의 of_device_id 테이블을 대조하여 어떤 드라이버를 실행할지 결정합니다.
/* 드라이버 코드 내부 */
static const struct of_device_id my_driver_match[] = {
{ .compatible = "myvendor,my-soc-uart", }, // DTS의 compatible과 일치해야 함
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, my_driver_match);
static struct platform_driver my_uart_driver = {
.probe = my_uart_probe,
.driver = {
.name = "my-soc-uart",
.of_match_table = my_driver_match, // 여기서 매칭 발생
},
};
2. probe 함수에서 데이터 추출하기 (Probing)
드라이버의 probe 함수 내에서 struct device_node를 통해 데이터를 가져옵니다.
매칭이 성공하면 커널은 probe 함수를 호출합니다. 이때 platform_device 구조체를 통해 해당 노드의 정보(dev.of_node)가 전달됩니다.
주요 데이터 타입별 추출 함수 예시
① 기본 속성 읽기 (u32, string 등)
of_property_read_... 계열 함수를 사용합니다.
static int my_uart_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; // DTS 노드 포인터
u32 reg_shift, val;
const char *status;
// u32 값 읽기: <2> 가져오기
if (!of_property_read_u32(np, "reg-shift", &val)) {
dev_info(dev, "reg-shift is %u\n", val);
}
// 문자열 읽기
of_property_read_string(np, "status", &status);
}
② 리소스(메모리, 인터럽트) 가져오기
reg나 interrupts는 하드웨어 제어의 핵심이므로 전용 헬퍼 함수를 씁니다.
// reg = <0x1c28000 0x400> 주소 정보 가져오기 및 매핑
struct resource *res;
void __iomem *base;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) return PTR_ERR(base);
// interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH> 번호 가져오기
int irq = platform_get_irq(pdev, 0);
3. Phandle을 통한 복잡한 관계 해석
DTS의 묘미는 clocks = <&ccu CLK_UART0>처럼 다른 노드를 참조하는 것입니다. 커널은 이 연결 고리를 따라가서 실제 객체를 찾아줍니다.
// 클럭 컨트롤러 노드를 찾아 클럭 객체 가져오기
struct clk *uart_clk;
uart_clk = devm_clk_get(dev, NULL); // DTS의 'clocks' 속성을 자동 해석
// 전력(Regulator) 가져오기
struct regulator *vcc = devm_regulator_get(dev, "vdd");
4. 자주 사용하는 OF(Open Firmware) API 요약: 📋 데이터 타입별 매칭 API
| DTS 데이터 타입 | C 언어 API (주로 사용) |
| Boolean (빈 값) | of_property_read_bool(np, "prop") |
| u32 (<123>) | of_property_read_u32(np, "prop", &val) |
| String ("str") | of_property_read_string(np, "prop", &s) |
| Reg (주소) | platform_get_resource() 또는 devm_platform_ioremap_resource() |
| Interrupts | platform_get_irq() |
| Phandle (참조) | of_parse_phandle() 또는 서브시스템 전용 API (clk_get, gpiod_get 등) |
※ 왜 of_get_property() 보다 of_property_read_...를 권장하나요?
- 안전성: of_property_read 계열 함수는 엔디안(Endian) 변환을 자동으로 처리해주며, 버퍼 오버플로우를 방지하는 체크 로직이 포함되어 있습니다.
- 편의성: 원시 바이트 데이터를 직접 파싱할 필요 없이 원하는 타입으로 바로 결과를 받을 수 있습니다.
💡 요약하자면:
DTS는 하드웨어 정보(배치도, Data)를 보관하고,
커널은 부팅 시 이 데이터를 메모리에 트리 구조(device_node)로 올립니다.
커널 드라이버는 of_ API를 사용하여 그 보관함에서 필요한 정보를 꺼내 하드웨어를 초기화합니다.
드라이버는 compatible 문자열로 자기 짝을 찾고, of_API 함수들을 호출해 배치도에 적힌 "주소", "핀 번호", "전압" 등을 읽어서 실제 레지스터를 조작하기 시작합니다.

참조: https://www.minzkn.com/linuxkernel/pages/device-tree.html#dt-device-node
'Embedded : : Linux > : : Device Tree' 카테고리의 다른 글
| [Device Tree] 6. Device Tree Overlay (DTBO) (0) | 2026.03.04 |
|---|---|
| [Device Tree] 5. .dtsi 인클루드 구조와 오버라이드 (0) | 2026.03.04 |
| [Device Tree] 3. DTS 문법 상세 (0) | 2026.03.04 |
| [Device Tree 심화] 1. Intro / 2. DT Architecture (0) | 2026.03.04 |
| Device Tree (0) | 2025.02.26 |