Herd Your Boards, Become a Farmer
Embedded Recipes 2019
Geert Uytterhoeven
geert@linux-m68k.org
GLIDER bvba
September 23, 2019
© Copyright 2019 GLIDER bvba, CC BY-SA 4.0
Herd Your SoCs, Become a Matchmaker
Embedded Recipes 2019
Geert Uytterhoeven
geert@linux-m68k.org
GLIDER bvba
September 23, 2019
© Copyright 2019 GLIDER bvba, CC BY-SA 4.0
Table of Contents
Introduction
History
Device Tree Bindings
Drivers
Final Words
2 / 35
My Linux Subsystems
Maintainer of Renesas clock and pin control drivers
since 2016
Maintainer of Renesas ARM SoC platforms
since July 2019
3 / 35
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
What Is Matching?
Finding a suitable driver for a piece of hardware
4 / 35
What Is Matching?
Finding a suitable driver for a piece of hardware
+ Identifying and using (all) available capabilities
4 / 35
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
Table of Contents
Introduction
History
Device Tree Bindings
Drivers
Final Words
5 / 35
A long time ago in a galaxy far, far away . . .
x86
Kernel configuration: per-machine → not scalable!
ISA probing
6 / 35
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
Rise of the Discoverable Buses
Discoverable Buses
PCI
Zorro (Amiga)
NuBus (Mac)
SBUS (SPARC)
. . .
Image © 20th Century Fox
7 / 35
Rise of the Discoverable Buses
Discoverable Buses
PCI
Zorro (Amiga)
NuBus (Mac)
SBUS (SPARC)
. . .
find() API
pci_find_device()
zorro_find_device()
for_each_sbus{,dev}()
. . .
+ Resource management
request_{mem_}region()
Image © 20th Century Fox
7 / 35
Device Framework (2001)
Triggered by hot-pluggable buses (e.g. USB)
Separation bus / device / driver
pci_{device,driver}
zorro_{device,driver}
platform_{device,driver}
. . .
Core matches devices to drivers based on IDs
8 / 35
Device Framework (2001)
Triggered by hot-pluggable buses (e.g. USB)
Separation bus / device / driver
pci_{device,driver}
zorro_{device,driver}
platform_{device,driver}
. . .
Core matches devices to drivers based on IDs
match() API
struct bus_type {
int (*match)(struct device *dev,
struct device_driver *drv);
};
8 / 35
Embedded: Return Of The Non-Discoverable Buses
Non-Discoverable Buses
Growing integration: SoC
Exponentially growing
number of SoC families,
versions, and revisions
Standardized components on
board
Hardware description:
board files with
platform_device +
platform_data
Linus’ 2010 rant about ARM
churn
Image © 20th Century Fox
9 / 35
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
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
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
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
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
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
soc_device_match() (2016)
Different approach, in-kernel
Wildcards!
If all else fails. . .
struct soc_device_attribute {
const char *machine;
const char *family;
const char *revision;
const char *serial_number;
const char *soc_id;
const void *data;
};
const struct soc_device_attribute *soc_device_match(
const struct soc_device_attribute *matches);
13 / 35
Table of Contents
Introduction
History
Device Tree Bindings
Drivers
Final Words
14 / 35
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
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
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
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
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
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
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
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
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
Table of Contents
Introduction
History
Device Tree Bindings
Drivers
Final Words
20 / 35
Supporting a Variety of Similar Devices
Similar devices on (a family of) SoCs may have:
Slightly differing feature sets
Quirks/bugs
21 / 35
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
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
Quirk Classes
Variant-Specific
How to handle? Device compatible value
Example: New or missing features
22 / 35
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
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
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
Matching Methods
1. platform_driver.driver.of_match_table
24 / 35
Matching Methods
1. platform_driver.driver.of_match_table
2. *_OF_DECLARE()
Early (for clocks, timers, irqchips)
X Dependencies on clocks/power domains/interrupts
X No -EPROBE_DEFER
Mixed: CLK_OF_DECLARE_DRIVER
24 / 35
Matching Methods
1. platform_driver.driver.of_match_table
2. *_OF_DECLARE()
Early (for clocks, timers, irqchips)
X Dependencies on clocks/power domains/interrupts
X No -EPROBE_DEFER
Mixed: CLK_OF_DECLARE_DRIVER
3. for_each_compatible_node()
of_find_compatible_node()
of_find_matching_node()
of_device_is_compatible()
24 / 35
Matching Methods
1. platform_driver.driver.of_match_table
2. *_OF_DECLARE()
Early (for clocks, timers, irqchips)
X Dependencies on clocks/power domains/interrupts
X No -EPROBE_DEFER
Mixed: CLK_OF_DECLARE_DRIVER
3. for_each_compatible_node()
of_find_compatible_node()
of_find_matching_node()
of_device_is_compatible()
4. soc_device_match()
24 / 35
Naive/Bad Examples
if (of_device_is_compatible(np, "myvendor,mydev")) {
...
}
if (soc_device_match(&myrev1) ||
soc_device_match(&myrev2)) {
...
}
25 / 35
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
Example: Scalar Feature Mask
drivers/clk/renesas/rcar-gen3-cpg.c
static const struct soc_device_attribute cpg_quirks_match[] = {
{
.soc_id = "r8a7795", .revision = "ES1.0",
.data = (void *)(PLL_ERRATA | RCKCR_CKSEL | ...),
},
...
};
int rcar_gen3_cpg_init(...)
{
const struct soc_device_attribute *attr;
attr = soc_device_match(cpg_quirks_match);
if (attr)
cpg_quirks = (uintptr_t)attr->data;
}
// Later...
if (cpg_quirks & ...) { ... }
26 / 35
Example: Feature Structure, Combined
drivers/media/platform/rcar-vin/rcar-core.c
static const struct of_device_id rvin_of_id_table[] = {
{
.compatible = "renesas,vin-r8a7795",
.data = &rcar_info_r8a7795,
}, ...
};
static const struct soc_device_attribute r8a7795es1[] = {
{
.soc_id = "r8a7795", .revision = "ES1.*",
.data = &rcar_info_r8a7795es1,
}, ...
};
static int rcar_vin_probe(struct platform_device *pdev)
{
vin->info = of_device_get_match_data(&pdev->dev);
attr = soc_device_match(r8a7795es1);
if (attr)
vin->info = attr->data;
}
27 / 35
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
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
Table of Contents
Introduction
History
Device Tree Bindings
Drivers
Final Words
29 / 35
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
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
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
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
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
Questions?
? 35 / 35

Embedded Recipes 2019 - Herd your socs become a matchmaker

  • 1.
    Herd Your Boards,Become a Farmer Embedded Recipes 2019 Geert Uytterhoeven geert@linux-m68k.org GLIDER bvba September 23, 2019 © Copyright 2019 GLIDER bvba, CC BY-SA 4.0
  • 2.
    Herd Your SoCs,Become a Matchmaker Embedded Recipes 2019 Geert Uytterhoeven geert@linux-m68k.org GLIDER bvba September 23, 2019 © Copyright 2019 GLIDER bvba, CC BY-SA 4.0
  • 3.
    Table of Contents Introduction History DeviceTree Bindings Drivers Final Words 2 / 35
  • 4.
    My Linux Subsystems Maintainerof Renesas clock and pin control drivers since 2016 Maintainer of Renesas ARM SoC platforms since July 2019 3 / 35
  • 5.
    My Linux Subsystems Maintainerof 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
  • 6.
    What Is Matching? Findinga suitable driver for a piece of hardware 4 / 35
  • 7.
    What Is Matching? Findinga suitable driver for a piece of hardware + Identifying and using (all) available capabilities 4 / 35
  • 8.
    What Is Matching? Findinga suitable driver for a piece of hardware + Identifying and using (all) available capabilities − Handling hardware-specific quirks/bugs/limitations 4 / 35
  • 9.
    Table of Contents Introduction History DeviceTree Bindings Drivers Final Words 5 / 35
  • 10.
    A long timeago in a galaxy far, far away . . . x86 Kernel configuration: per-machine → not scalable! ISA probing 6 / 35
  • 11.
    A long timeago 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
  • 12.
    Rise of theDiscoverable Buses Discoverable Buses PCI Zorro (Amiga) NuBus (Mac) SBUS (SPARC) . . . Image © 20th Century Fox 7 / 35
  • 13.
    Rise of theDiscoverable Buses Discoverable Buses PCI Zorro (Amiga) NuBus (Mac) SBUS (SPARC) . . . find() API pci_find_device() zorro_find_device() for_each_sbus{,dev}() . . . + Resource management request_{mem_}region() Image © 20th Century Fox 7 / 35
  • 14.
    Device Framework (2001) Triggeredby hot-pluggable buses (e.g. USB) Separation bus / device / driver pci_{device,driver} zorro_{device,driver} platform_{device,driver} . . . Core matches devices to drivers based on IDs 8 / 35
  • 15.
    Device Framework (2001) Triggeredby hot-pluggable buses (e.g. USB) Separation bus / device / driver pci_{device,driver} zorro_{device,driver} platform_{device,driver} . . . Core matches devices to drivers based on IDs match() API struct bus_type { int (*match)(struct device *dev, struct device_driver *drv); }; 8 / 35
  • 16.
    Embedded: Return OfThe Non-Discoverable Buses Non-Discoverable Buses Growing integration: SoC Exponentially growing number of SoC families, versions, and revisions Standardized components on board Hardware description: board files with platform_device + platform_data Linus’ 2010 rant about ARM churn Image © 20th Century Fox 9 / 35
  • 17.
    Device Tree Real OpenFirmware 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 Straightconversion 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 Straightconversion 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 differentcompatible 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 differentcompatible 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 differentcompatible 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
  • 23.
    soc_device_match() (2016) Different approach,in-kernel Wildcards! If all else fails. . . struct soc_device_attribute { const char *machine; const char *family; const char *revision; const char *serial_number; const char *soc_id; const void *data; }; const struct soc_device_attribute *soc_device_match( const struct soc_device_attribute *matches); 13 / 35
  • 24.
    Table of Contents Introduction History DeviceTree Bindings Drivers Final Words 14 / 35
  • 25.
    Designing Compatible ValueSchemes The Original Series Basic Idea Multiple compatible values: most-specific to least-specific Driver matches against what is supported 15 / 35
  • 26.
    Designing Compatible ValueSchemes 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 ValueSchemes 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 ValueSchemes 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 DTBindings 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 DTBindings 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 CompatibleValues: 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 CompatibleValues: 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 WithinThe 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
  • 34.
    Table of Contents Introduction History DeviceTree Bindings Drivers Final Words 20 / 35
  • 35.
    Supporting a Varietyof Similar Devices Similar devices on (a family of) SoCs may have: Slightly differing feature sets Quirks/bugs 21 / 35
  • 36.
    Supporting a Varietyof 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 Varietyof 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
  • 38.
    Quirk Classes Variant-Specific How tohandle? Device compatible value Example: New or missing features 22 / 35
  • 39.
    Quirk Classes Variant-Specific How tohandle? 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 instanceon 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 instanceon 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
  • 42.
  • 43.
    Matching Methods 1. platform_driver.driver.of_match_table 2.*_OF_DECLARE() Early (for clocks, timers, irqchips) X Dependencies on clocks/power domains/interrupts X No -EPROBE_DEFER Mixed: CLK_OF_DECLARE_DRIVER 24 / 35
  • 44.
    Matching Methods 1. platform_driver.driver.of_match_table 2.*_OF_DECLARE() Early (for clocks, timers, irqchips) X Dependencies on clocks/power domains/interrupts X No -EPROBE_DEFER Mixed: CLK_OF_DECLARE_DRIVER 3. for_each_compatible_node() of_find_compatible_node() of_find_matching_node() of_device_is_compatible() 24 / 35
  • 45.
    Matching Methods 1. platform_driver.driver.of_match_table 2.*_OF_DECLARE() Early (for clocks, timers, irqchips) X Dependencies on clocks/power domains/interrupts X No -EPROBE_DEFER Mixed: CLK_OF_DECLARE_DRIVER 3. for_each_compatible_node() of_find_compatible_node() of_find_matching_node() of_device_is_compatible() 4. soc_device_match() 24 / 35
  • 46.
    Naive/Bad Examples if (of_device_is_compatible(np,"myvendor,mydev")) { ... } if (soc_device_match(&myrev1) || soc_device_match(&myrev2)) { ... } 25 / 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
  • 48.
    Example: Scalar FeatureMask drivers/clk/renesas/rcar-gen3-cpg.c static const struct soc_device_attribute cpg_quirks_match[] = { { .soc_id = "r8a7795", .revision = "ES1.0", .data = (void *)(PLL_ERRATA | RCKCR_CKSEL | ...), }, ... }; int rcar_gen3_cpg_init(...) { const struct soc_device_attribute *attr; attr = soc_device_match(cpg_quirks_match); if (attr) cpg_quirks = (uintptr_t)attr->data; } // Later... if (cpg_quirks & ...) { ... } 26 / 35
  • 49.
    Example: Feature Structure,Combined drivers/media/platform/rcar-vin/rcar-core.c static const struct of_device_id rvin_of_id_table[] = { { .compatible = "renesas,vin-r8a7795", .data = &rcar_info_r8a7795, }, ... }; static const struct soc_device_attribute r8a7795es1[] = { { .soc_id = "r8a7795", .revision = "ES1.*", .data = &rcar_info_r8a7795es1, }, ... }; static int rcar_vin_probe(struct platform_device *pdev) { vin->info = of_device_get_match_data(&pdev->dev); attr = soc_device_match(r8a7795es1); if (attr) vin->info = attr->data; } 27 / 35
  • 50.
    Different DTSes ForDifferent 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 ForDifferent 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
  • 52.
    Table of Contents Introduction History DeviceTree Bindings Drivers Final Words 29 / 35
  • 53.
    Has DT improvedthe 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 improvedthe 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 improvedthe 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 improvedthe 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 RenesasElectronics 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
  • 58.