1642e6e5cSMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0 2642e6e5cSMauro Carvalho Chehab 37248213cSRob Herring======================== 47248213cSRob HerringDevicetree Overlay Notes 57248213cSRob Herring======================== 6642e6e5cSMauro Carvalho Chehab 7642e6e5cSMauro Carvalho ChehabThis document describes the implementation of the in-kernel 8642e6e5cSMauro Carvalho Chehabdevice tree overlay functionality residing in drivers/of/overlay.c and is a 9642e6e5cSMauro Carvalho Chehabcompanion document to Documentation/devicetree/dynamic-resolution-notes.rst[1] 10642e6e5cSMauro Carvalho Chehab 11642e6e5cSMauro Carvalho ChehabHow overlays work 12642e6e5cSMauro Carvalho Chehab----------------- 13642e6e5cSMauro Carvalho Chehab 147248213cSRob HerringA Devicetree's overlay purpose is to modify the kernel's live tree, and 15642e6e5cSMauro Carvalho Chehabhave the modification affecting the state of the kernel in a way that 16642e6e5cSMauro Carvalho Chehabis reflecting the changes. 17642e6e5cSMauro Carvalho ChehabSince the kernel mainly deals with devices, any new device node that result 18642e6e5cSMauro Carvalho Chehabin an active device should have it created while if the device node is either 19642e6e5cSMauro Carvalho Chehabdisabled or removed all together, the affected device should be deregistered. 20642e6e5cSMauro Carvalho Chehab 21642e6e5cSMauro Carvalho ChehabLets take an example where we have a foo board with the following base tree:: 22642e6e5cSMauro Carvalho Chehab 23642e6e5cSMauro Carvalho Chehab ---- foo.dts --------------------------------------------------------------- 24642e6e5cSMauro Carvalho Chehab /* FOO platform */ 25642e6e5cSMauro Carvalho Chehab /dts-v1/; 26642e6e5cSMauro Carvalho Chehab / { 27642e6e5cSMauro Carvalho Chehab compatible = "corp,foo"; 28642e6e5cSMauro Carvalho Chehab 29642e6e5cSMauro Carvalho Chehab /* shared resources */ 30642e6e5cSMauro Carvalho Chehab res: res { 31642e6e5cSMauro Carvalho Chehab }; 32642e6e5cSMauro Carvalho Chehab 33642e6e5cSMauro Carvalho Chehab /* On chip peripherals */ 34642e6e5cSMauro Carvalho Chehab ocp: ocp { 35642e6e5cSMauro Carvalho Chehab /* peripherals that are always instantiated */ 36642e6e5cSMauro Carvalho Chehab peripheral1 { ... }; 37642e6e5cSMauro Carvalho Chehab }; 38642e6e5cSMauro Carvalho Chehab }; 39642e6e5cSMauro Carvalho Chehab ---- foo.dts --------------------------------------------------------------- 40642e6e5cSMauro Carvalho Chehab 41642e6e5cSMauro Carvalho ChehabThe overlay bar.dts, 42642e6e5cSMauro Carvalho Chehab:: 43642e6e5cSMauro Carvalho Chehab 44642e6e5cSMauro Carvalho Chehab ---- bar.dts - overlay target location by label ---------------------------- 45642e6e5cSMauro Carvalho Chehab /dts-v1/; 46642e6e5cSMauro Carvalho Chehab /plugin/; 47642e6e5cSMauro Carvalho Chehab &ocp { 48642e6e5cSMauro Carvalho Chehab /* bar peripheral */ 49642e6e5cSMauro Carvalho Chehab bar { 50642e6e5cSMauro Carvalho Chehab compatible = "corp,bar"; 51642e6e5cSMauro Carvalho Chehab ... /* various properties and child nodes */ 52642e6e5cSMauro Carvalho Chehab }; 53642e6e5cSMauro Carvalho Chehab }; 54642e6e5cSMauro Carvalho Chehab ---- bar.dts --------------------------------------------------------------- 55642e6e5cSMauro Carvalho Chehab 56642e6e5cSMauro Carvalho Chehabwhen loaded (and resolved as described in [1]) should result in foo+bar.dts:: 57642e6e5cSMauro Carvalho Chehab 58642e6e5cSMauro Carvalho Chehab ---- foo+bar.dts ----------------------------------------------------------- 59642e6e5cSMauro Carvalho Chehab /* FOO platform + bar peripheral */ 60642e6e5cSMauro Carvalho Chehab / { 61642e6e5cSMauro Carvalho Chehab compatible = "corp,foo"; 62642e6e5cSMauro Carvalho Chehab 63642e6e5cSMauro Carvalho Chehab /* shared resources */ 64642e6e5cSMauro Carvalho Chehab res: res { 65642e6e5cSMauro Carvalho Chehab }; 66642e6e5cSMauro Carvalho Chehab 67642e6e5cSMauro Carvalho Chehab /* On chip peripherals */ 68642e6e5cSMauro Carvalho Chehab ocp: ocp { 69642e6e5cSMauro Carvalho Chehab /* peripherals that are always instantiated */ 70642e6e5cSMauro Carvalho Chehab peripheral1 { ... }; 71642e6e5cSMauro Carvalho Chehab 72642e6e5cSMauro Carvalho Chehab /* bar peripheral */ 73642e6e5cSMauro Carvalho Chehab bar { 74642e6e5cSMauro Carvalho Chehab compatible = "corp,bar"; 75642e6e5cSMauro Carvalho Chehab ... /* various properties and child nodes */ 76642e6e5cSMauro Carvalho Chehab }; 77642e6e5cSMauro Carvalho Chehab }; 78642e6e5cSMauro Carvalho Chehab }; 79642e6e5cSMauro Carvalho Chehab ---- foo+bar.dts ----------------------------------------------------------- 80642e6e5cSMauro Carvalho Chehab 81642e6e5cSMauro Carvalho ChehabAs a result of the overlay, a new device node (bar) has been created 82642e6e5cSMauro Carvalho Chehabso a bar platform device will be registered and if a matching device driver 83642e6e5cSMauro Carvalho Chehabis loaded the device will be created as expected. 84642e6e5cSMauro Carvalho Chehab 85642e6e5cSMauro Carvalho ChehabIf the base DT was not compiled with the -@ option then the "&ocp" label 86642e6e5cSMauro Carvalho Chehabwill not be available to resolve the overlay node(s) to the proper location 87642e6e5cSMauro Carvalho Chehabin the base DT. In this case, the target path can be provided. The target 88642e6e5cSMauro Carvalho Chehablocation by label syntax is preferred because the overlay can be applied to 89642e6e5cSMauro Carvalho Chehabany base DT containing the label, no matter where the label occurs in the DT. 90642e6e5cSMauro Carvalho Chehab 91642e6e5cSMauro Carvalho ChehabThe above bar.dts example modified to use target path syntax is:: 92642e6e5cSMauro Carvalho Chehab 93642e6e5cSMauro Carvalho Chehab ---- bar.dts - overlay target location by explicit path -------------------- 94642e6e5cSMauro Carvalho Chehab /dts-v1/; 95642e6e5cSMauro Carvalho Chehab /plugin/; 96642e6e5cSMauro Carvalho Chehab &{/ocp} { 97642e6e5cSMauro Carvalho Chehab /* bar peripheral */ 98642e6e5cSMauro Carvalho Chehab bar { 99642e6e5cSMauro Carvalho Chehab compatible = "corp,bar"; 100642e6e5cSMauro Carvalho Chehab ... /* various properties and child nodes */ 101642e6e5cSMauro Carvalho Chehab } 102642e6e5cSMauro Carvalho Chehab }; 103642e6e5cSMauro Carvalho Chehab ---- bar.dts --------------------------------------------------------------- 104642e6e5cSMauro Carvalho Chehab 105642e6e5cSMauro Carvalho Chehab 106642e6e5cSMauro Carvalho ChehabOverlay in-kernel API 107642e6e5cSMauro Carvalho Chehab-------------------------------- 108642e6e5cSMauro Carvalho Chehab 109642e6e5cSMauro Carvalho ChehabThe API is quite easy to use. 110642e6e5cSMauro Carvalho Chehab 111642e6e5cSMauro Carvalho Chehab1) Call of_overlay_fdt_apply() to create and apply an overlay changeset. The 112642e6e5cSMauro Carvalho Chehab return value is an error or a cookie identifying this overlay. 113642e6e5cSMauro Carvalho Chehab 114642e6e5cSMauro Carvalho Chehab2) Call of_overlay_remove() to remove and cleanup the overlay changeset 115642e6e5cSMauro Carvalho Chehab previously created via the call to of_overlay_fdt_apply(). Removal of an 116642e6e5cSMauro Carvalho Chehab overlay changeset that is stacked by another will not be permitted. 117642e6e5cSMauro Carvalho Chehab 118642e6e5cSMauro Carvalho ChehabFinally, if you need to remove all overlays in one-go, just call 119642e6e5cSMauro Carvalho Chehabof_overlay_remove_all() which will remove every single one in the correct 120642e6e5cSMauro Carvalho Chehaborder. 121642e6e5cSMauro Carvalho Chehab 122*067c0987SFrank RowandThere is the option to register notifiers that get called on 123642e6e5cSMauro Carvalho Chehaboverlay operations. See of_overlay_notifier_register/unregister and 124642e6e5cSMauro Carvalho Chehabenum of_overlay_notify_action for details. 125642e6e5cSMauro Carvalho Chehab 126*067c0987SFrank RowandA notifier callback for OF_OVERLAY_PRE_APPLY, OF_OVERLAY_POST_APPLY, or 127*067c0987SFrank RowandOF_OVERLAY_PRE_REMOVE may store pointers to a device tree node in the overlay 128*067c0987SFrank Rowandor its content but these pointers must not persist past the notifier callback 129*067c0987SFrank Rowandfor OF_OVERLAY_POST_REMOVE. The memory containing the overlay will be 130*067c0987SFrank Rowandkfree()ed after OF_OVERLAY_POST_REMOVE notifiers are called. Note that the 131*067c0987SFrank Rowandmemory will be kfree()ed even if the notifier for OF_OVERLAY_POST_REMOVE 132*067c0987SFrank Rowandreturns an error. 133*067c0987SFrank Rowand 134*067c0987SFrank RowandThe changeset notifiers in drivers/of/dynamic.c are a second type of notifier 135*067c0987SFrank Rowandthat could be triggered by applying or removing an overlay. These notifiers 136*067c0987SFrank Rowandare not allowed to store pointers to a device tree node in the overlay 137*067c0987SFrank Rowandor its content. The overlay code does not protect against such pointers 138*067c0987SFrank Rowandremaining active when the memory containing the overlay is freed as a result 139*067c0987SFrank Rowandof removing the overlay. 140*067c0987SFrank Rowand 141*067c0987SFrank RowandAny other code that retains a pointer to the overlay nodes or data is 142*067c0987SFrank Rowandconsidered to be a bug because after removing the overlay the pointer 143*067c0987SFrank Rowandwill refer to freed memory. 144*067c0987SFrank Rowand 145*067c0987SFrank RowandUsers of overlays must be especially aware of the overall operations that 146*067c0987SFrank Rowandoccur on the system to ensure that other kernel code does not retain any 147*067c0987SFrank Rowandpointers to the overlay nodes or data. Any example of an inadvertent use 148*067c0987SFrank Rowandof such pointers is if a driver or subsystem module is loaded after an 149*067c0987SFrank Rowandoverlay has been applied, and the driver or subsystem scans the entire 150*067c0987SFrank Rowanddevicetree or a large portion of it, including the overlay nodes. 151