This document discusses device tree matching for embedded systems. It covers:
- The history of device matching in Linux, from architecture-specific to discoverable buses to the modern device framework.
- How device trees improved the situation by providing a standardized hardware description and stable ABI, separating this from OS configuration.
- Best practices for designing compatible value schemes and supporting a variety of similar devices across SoC families in device trees and drivers.
- Different techniques for matching devices and drivers like compatible values, soc_device_match(), and quirk handling classes.
- Examples of implementing matching for Renesas SoCs and addressing differences across revisions.
4. My Linux Subsystems
Maintainer of Renesas clock and pin control drivers
since 2016
Maintainer of Renesas ARM SoC platforms
since July 2019
3 / 35
5. My Linux Subsystems
Maintainer of Renesas clock and pin control drivers
since 2016
Maintainer of Renesas ARM SoC platforms
since July 2019
LTSI Submaintainer
since July 2018
Maintainer of the m68k architecture
since 2004
3 / 35
7. What Is Matching?
Finding a suitable driver for a piece of hardware
+ Identifying and using (all) available capabilities
4 / 35
8. What Is Matching?
Finding a suitable driver for a piece of hardware
+ Identifying and using (all) available capabilities
− Handling hardware-specific quirks/bugs/limitations
4 / 35
10. A long time ago in a galaxy far, far away . . .
x86
Kernel configuration: per-machine → not scalable!
ISA probing
6 / 35
11. A long time ago in a galaxy far, far away . . .
x86
Kernel configuration: per-machine → not scalable!
ISA probing
Multi-platform
Machine type (m68k, MIPS, SPARC)
Tagged bootinfo (m68k, ARM, MIPS)
Info passed by bootloader or IDPROM
6 / 35
17. Device Tree
Real Open Firmware
Flattened Device Tree
Device ⇔ device node
Compatible value(s)
Standard properties (resources, . . . )
Custom properties
Phandles
Subnodes
Clear separation between Hardware Description and
OS Configuration
Stable DT ABI
Ties into platform_device
10 / 35
18. DT Early Adopters
Straight conversion from platform_data to DT
properties
Same compatible value, many feature properties
⇒ All detail in DT
CCF: Collection of device nodes for on-SoC clock
generator
Standard and custom parts
Individual bits described in DT
11 / 35
19. DT Early Adopters
Straight conversion from platform_data to DT
properties
Same compatible value, many feature properties
⇒ All detail in DT
CCF: Collection of device nodes for on-SoC clock
generator
Standard and custom parts
Individual bits described in DT
Caveats
You will forget to describe a difference, difficult to fix later!
New SoC reuses block with e.g. different predivider
⇒ DT property
Newer block with different predivider now also supported!
What if another difference is discovered later?
11 / 35
20. DT Evolution/Maturity
More different compatible values, few/no feature properties
Clocks: "monolithic" device node for on-SoC clock
generator
⇒ Easier to extend/maintain
12 / 35
21. DT Evolution/Maturity
More different compatible values, few/no feature properties
Clocks: "monolithic" device node for on-SoC clock
generator
⇒ Easier to extend/maintain
ELCE2014: Engaging Device Trees
Still good?
12 / 35
22. DT Evolution/Maturity
More different compatible values, few/no feature properties
Clocks: "monolithic" device node for on-SoC clock
generator
⇒ Easier to extend/maintain
ELCE2014: Engaging Device Trees
Still good? Yes! (surprisingly?)
Clocks:
Moved from collection of nodes to a monolithic approach
(DT without Common Clock Framework is dead)
Power Domains: similar, but didn’t have DT bindings yet
https://elinux.org/ELC_2014_Presentations
12 / 35
25. Designing Compatible Value Schemes
The Original Series
Basic Idea
Multiple compatible values: most-specific to least-specific
Driver matches against what is supported
15 / 35
26. Designing Compatible Value Schemes
The Original Series
Basic Idea
Multiple compatible values: most-specific to least-specific
Driver matches against what is supported
Original: current version + older compatible version
Suitable for slow evolution
E.g. 8250 → 16450 → 16550 UART Bad example!
Discrete components
E.g. WLAN controller
15 / 35
27. Designing Compatible Value Schemes
A Brave New World
Fast Evolution
Building an SoC ∼ LEGO, Kconfig
Complex heritage hierarchy (copy and corrupt^Wmodify)
Which one is predecessor/successor?
Do all family members have the same version?
16 / 35
28. Designing Compatible Value Schemes
A Brave New World
Fast Evolution
Building an SoC ∼ LEGO, Kconfig
Complex heritage hierarchy (copy and corrupt^Wmodify)
Which one is predecessor/successor?
Do all family members have the same version?
SiFive
sifive,<ip-block-name><integer version number>
E.g. sifive,uart0
16 / 35
29. Example: Renesas DT Bindings For On-SoC Devices
1. SoC-specific (always, unless version register present)
E.g. renesas,r8a7791-sysc, renesas,r8a7795-wdt
→ To anticipate unknown differences
2. Family-specific (usually)
E.g. renesas,rcar-gen2-scif
3. Generic (sometimes: legacy or version register)
E.g. renesas,scif or renesas,vsp2
17 / 35
30. Example: Renesas DT Bindings For On-SoC Devices
1. SoC-specific (always, unless version register present)
E.g. renesas,r8a7791-sysc, renesas,r8a7795-wdt
→ To anticipate unknown differences
2. Family-specific (usually)
E.g. renesas,rcar-gen2-scif
3. Generic (sometimes: legacy or version register)
E.g. renesas,scif or renesas,vsp2
DT bindings document all of the above (checkpatch.pl!)
DTS advertizes all of the above
Driver matches against least-specific that will do the job
17 / 35
31. Renesas DT Compatible Values: Statistics
Linux v5.3:
Type Documented Used Matched
SoC-specific 743 688 296
Family-specific 92 82 85
Generic 30 29 28
18 / 35
32. Renesas DT Compatible Values: Statistics
Linux v5.3:
Type Documented Used Matched
SoC-specific 743 688 296
Family-specific 92 82 85
Generic 30 29 28
Is proliferation of compatible values, and churn on the DT
binding documents, worth it?
18 / 35
33. Example: Differences Within The Same Family
Obvious for e.g. clocks, power domains, pin controllers,
Unexpected (R-Car Gen3 only):
DRIF Extra register on M3-N and E3,
LVDS Not uniform, unlike on Gen2,
PCIe Extra PHY register on V3H,
RPC-IF Several differences,
Sound R-Car E3 special handling was bolted on later,
Thermal M3-W turned out to have a different Tj,
USBHS Wrongly assumed identical to Gen2,
E3/D3 use a different PLL,
VIN Not uniform, unlike on Gen2.
Compare: 23 family-specific values for R-Car Gen3.
19 / 35
35. Supporting a Variety of Similar Devices
Similar devices on (a family of) SoCs may have:
Slightly differing feature sets
Quirks/bugs
21 / 35
36. Supporting a Variety of Similar Devices
Similar devices on (a family of) SoCs may have:
Slightly differing feature sets
Quirks/bugs
Differentiate by:
Compatible value
Machine, family, revision, serial number, soc_id
+ wildcards (e.g. .revision = "ES1.*")
Device address?
21 / 35
37. Supporting a Variety of Similar Devices
Similar devices on (a family of) SoCs may have:
Slightly differing feature sets
Quirks/bugs
Differentiate by:
Compatible value
Machine, family, revision, serial number, soc_id
+ wildcards (e.g. .revision = "ES1.*")
Device address?
Solutions
1. Match on compatible value
2. struct soc_device_attribute and
soc_device_match()
21 / 35
39. Quirk Classes
Variant-Specific
How to handle? Device compatible value
Example: New or missing features
SoC-Specific / SoC Integration Issue
How to handle?
Device compatible value
soc_device_match()
Example: Broken DMA on early revision
22 / 35
40. Quirk Classes
Instance-Specific
One instance on SoC affected
How to handle?
Device base address + soc_device_match()
DT property / Device compatible value
Example: Broken interrupt on one instance
23 / 35
41. Quirk Classes
Instance-Specific
One instance on SoC affected
How to handle?
Device base address + soc_device_match()
DT property / Device compatible value
Example: Broken interrupt on one instance
Board-Specific
How to handle? Board compatible value
Example: R-Car Gen2 regulator quirk
23 / 35
47. Naive/Bad Examples
if (of_device_is_compatible(np, "myvendor,mydev")) {
...
}
if (soc_device_match(&myrev1) ||
soc_device_match(&myrev2)) {
...
}
Called multiple times?
From an interrupt handler?
Not scalable!
25 / 35
50. Different DTSes For Different SoC Revisions
Include new SoC .dtsi in old .dtsi
Add/override nodes and properties
/delete-node/, /delete-property/
Use soc_device_match() to differentiate
28 / 35
51. Different DTSes For Different SoC Revisions
Include new SoC .dtsi in old .dtsi
Add/override nodes and properties
/delete-node/, /delete-property/
Use soc_device_match() to differentiate
Example
R-Car H3 ES1.x (R8A77950) and ES2.0 (R8A77951)
both use r8a7795-based compatible values
In hindsight:
ES2.0 is a new SoC, not just a fixed ES1.x
New r8a77951-based compatible values
28 / 35
53. Has DT improved the ARM situation?
Evolution of the number of ARM defconfig files (ELC2014)
0
20
40
60
80
100
120
140
160
180
v2.6.14
v2.6.19
v2.6.24
v2.6.29
v2.6.34
v2.6.39
v3.4
v3.9
v3.14
30 / 35
54. Has DT improved the ARM situation?
Evolution of the number of ARM defconfig files
0
20
40
60
80
100
120
140
160
180
v2.6.14v2.6.19v2.6.24v2.6.29v2.6.34v2.6.39v3.4
v3.9
v3.14
v3.19
v4.4
v4.9
v4.14
v4.19
v5.3
31 / 35
55. Has DT improved the ARM situation?
Evolution of the number of ARM DTS files
0
200
400
600
800
1000
1200 v3.4
v3.9
v3.14
v3.19
v4.4
v4.9
v4.14
v4.19
v5.3
arm32
arm64
32 / 35
56. Has DT improved the ARM situation?
Evolution of the number of lines in ARM board files and ARM DTS files
0
100000
200000
300000
400000
500000
600000 v2.6.14v2.6.19v2.6.24v2.6.29v2.6.34v2.6.39v3.4
v3.9
v3.14
v3.19
v4.4
v4.9
v4.14
v4.19
v5.3
arm32 board
arm32 DTS
arm64 DTS
33 / 35
57. Thanks & Acknowledgements
Renesas Electronics Corporation, for contracting me for
upstream Linux kernel work,
Embedded Recipes, for organizing this conference and
giving me the opportunity to present here,
The Linux Kernel Community, for having so much fun
working together towards a common goal.
34 / 35