1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun========================= 4*4882a593SmuzhiyunDevice Tree Overlay Notes 5*4882a593Smuzhiyun========================= 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunThis document describes the implementation of the in-kernel 8*4882a593Smuzhiyundevice tree overlay functionality residing in drivers/of/overlay.c and is a 9*4882a593Smuzhiyuncompanion document to Documentation/devicetree/dynamic-resolution-notes.rst[1] 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunHow overlays work 12*4882a593Smuzhiyun----------------- 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunA Device Tree's overlay purpose is to modify the kernel's live tree, and 15*4882a593Smuzhiyunhave the modification affecting the state of the kernel in a way that 16*4882a593Smuzhiyunis reflecting the changes. 17*4882a593SmuzhiyunSince the kernel mainly deals with devices, any new device node that result 18*4882a593Smuzhiyunin an active device should have it created while if the device node is either 19*4882a593Smuzhiyundisabled or removed all together, the affected device should be deregistered. 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunLets take an example where we have a foo board with the following base tree:: 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun ---- foo.dts --------------------------------------------------------------- 24*4882a593Smuzhiyun /* FOO platform */ 25*4882a593Smuzhiyun /dts-v1/; 26*4882a593Smuzhiyun / { 27*4882a593Smuzhiyun compatible = "corp,foo"; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun /* shared resources */ 30*4882a593Smuzhiyun res: res { 31*4882a593Smuzhiyun }; 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /* On chip peripherals */ 34*4882a593Smuzhiyun ocp: ocp { 35*4882a593Smuzhiyun /* peripherals that are always instantiated */ 36*4882a593Smuzhiyun peripheral1 { ... }; 37*4882a593Smuzhiyun }; 38*4882a593Smuzhiyun }; 39*4882a593Smuzhiyun ---- foo.dts --------------------------------------------------------------- 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunThe overlay bar.dts, 42*4882a593Smuzhiyun:: 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun ---- bar.dts - overlay target location by label ---------------------------- 45*4882a593Smuzhiyun /dts-v1/; 46*4882a593Smuzhiyun /plugin/; 47*4882a593Smuzhiyun &ocp { 48*4882a593Smuzhiyun /* bar peripheral */ 49*4882a593Smuzhiyun bar { 50*4882a593Smuzhiyun compatible = "corp,bar"; 51*4882a593Smuzhiyun ... /* various properties and child nodes */ 52*4882a593Smuzhiyun }; 53*4882a593Smuzhiyun }; 54*4882a593Smuzhiyun ---- bar.dts --------------------------------------------------------------- 55*4882a593Smuzhiyun 56*4882a593Smuzhiyunwhen loaded (and resolved as described in [1]) should result in foo+bar.dts:: 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun ---- foo+bar.dts ----------------------------------------------------------- 59*4882a593Smuzhiyun /* FOO platform + bar peripheral */ 60*4882a593Smuzhiyun / { 61*4882a593Smuzhiyun compatible = "corp,foo"; 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun /* shared resources */ 64*4882a593Smuzhiyun res: res { 65*4882a593Smuzhiyun }; 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun /* On chip peripherals */ 68*4882a593Smuzhiyun ocp: ocp { 69*4882a593Smuzhiyun /* peripherals that are always instantiated */ 70*4882a593Smuzhiyun peripheral1 { ... }; 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun /* bar peripheral */ 73*4882a593Smuzhiyun bar { 74*4882a593Smuzhiyun compatible = "corp,bar"; 75*4882a593Smuzhiyun ... /* various properties and child nodes */ 76*4882a593Smuzhiyun }; 77*4882a593Smuzhiyun }; 78*4882a593Smuzhiyun }; 79*4882a593Smuzhiyun ---- foo+bar.dts ----------------------------------------------------------- 80*4882a593Smuzhiyun 81*4882a593SmuzhiyunAs a result of the overlay, a new device node (bar) has been created 82*4882a593Smuzhiyunso a bar platform device will be registered and if a matching device driver 83*4882a593Smuzhiyunis loaded the device will be created as expected. 84*4882a593Smuzhiyun 85*4882a593SmuzhiyunIf the base DT was not compiled with the -@ option then the "&ocp" label 86*4882a593Smuzhiyunwill not be available to resolve the overlay node(s) to the proper location 87*4882a593Smuzhiyunin the base DT. In this case, the target path can be provided. The target 88*4882a593Smuzhiyunlocation by label syntax is preferred because the overlay can be applied to 89*4882a593Smuzhiyunany base DT containing the label, no matter where the label occurs in the DT. 90*4882a593Smuzhiyun 91*4882a593SmuzhiyunThe above bar.dts example modified to use target path syntax is:: 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun ---- bar.dts - overlay target location by explicit path -------------------- 94*4882a593Smuzhiyun /dts-v1/; 95*4882a593Smuzhiyun /plugin/; 96*4882a593Smuzhiyun &{/ocp} { 97*4882a593Smuzhiyun /* bar peripheral */ 98*4882a593Smuzhiyun bar { 99*4882a593Smuzhiyun compatible = "corp,bar"; 100*4882a593Smuzhiyun ... /* various properties and child nodes */ 101*4882a593Smuzhiyun } 102*4882a593Smuzhiyun }; 103*4882a593Smuzhiyun ---- bar.dts --------------------------------------------------------------- 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun 106*4882a593SmuzhiyunOverlay in-kernel API 107*4882a593Smuzhiyun-------------------------------- 108*4882a593Smuzhiyun 109*4882a593SmuzhiyunThe API is quite easy to use. 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun1) Call of_overlay_fdt_apply() to create and apply an overlay changeset. The 112*4882a593Smuzhiyun return value is an error or a cookie identifying this overlay. 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun2) Call of_overlay_remove() to remove and cleanup the overlay changeset 115*4882a593Smuzhiyun previously created via the call to of_overlay_fdt_apply(). Removal of an 116*4882a593Smuzhiyun overlay changeset that is stacked by another will not be permitted. 117*4882a593Smuzhiyun 118*4882a593SmuzhiyunFinally, if you need to remove all overlays in one-go, just call 119*4882a593Smuzhiyunof_overlay_remove_all() which will remove every single one in the correct 120*4882a593Smuzhiyunorder. 121*4882a593Smuzhiyun 122*4882a593SmuzhiyunIn addition, there is the option to register notifiers that get called on 123*4882a593Smuzhiyunoverlay operations. See of_overlay_notifier_register/unregister and 124*4882a593Smuzhiyunenum of_overlay_notify_action for details. 125*4882a593Smuzhiyun 126*4882a593SmuzhiyunNote that a notifier callback is not supposed to store pointers to a device 127*4882a593Smuzhiyuntree node or its content beyond OF_OVERLAY_POST_REMOVE corresponding to the 128*4882a593Smuzhiyunrespective node it received. 129