151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
.. SPDX-License-Identifier: GPL-2.0
 | 
						|
 | 
						|
========================
 | 
						|
Devicetree Overlay Notes
 | 
						|
========================
 | 
						|
 | 
						|
This document describes the implementation of the in-kernel
 | 
						|
device tree overlay functionality residing in drivers/of/overlay.c and is a
 | 
						|
companion document to Documentation/devicetree/dynamic-resolution-notes.rst[1]
 | 
						|
 | 
						|
How overlays work
 | 
						|
-----------------
 | 
						|
 | 
						|
A Devicetree's overlay purpose is to modify the kernel's live tree, and
 | 
						|
have the modification affecting the state of the kernel in a way that
 | 
						|
is reflecting the changes.
 | 
						|
Since the kernel mainly deals with devices, any new device node that result
 | 
						|
in an active device should have it created while if the device node is either
 | 
						|
disabled or removed all together, the affected device should be deregistered.
 | 
						|
 | 
						|
Lets take an example where we have a foo board with the following base tree::
 | 
						|
 | 
						|
    ---- foo.dts ---------------------------------------------------------------
 | 
						|
	/* FOO platform */
 | 
						|
	/dts-v1/;
 | 
						|
	/ {
 | 
						|
		compatible = "corp,foo";
 | 
						|
 | 
						|
		/* shared resources */
 | 
						|
		res: res {
 | 
						|
		};
 | 
						|
 | 
						|
		/* On chip peripherals */
 | 
						|
		ocp: ocp {
 | 
						|
			/* peripherals that are always instantiated */
 | 
						|
			peripheral1 { ... };
 | 
						|
		};
 | 
						|
	};
 | 
						|
    ---- foo.dts ---------------------------------------------------------------
 | 
						|
 | 
						|
The overlay bar.dts,
 | 
						|
::
 | 
						|
 | 
						|
    ---- bar.dts - overlay target location by label ----------------------------
 | 
						|
	/dts-v1/;
 | 
						|
	/plugin/;
 | 
						|
	&ocp {
 | 
						|
		/* bar peripheral */
 | 
						|
		bar {
 | 
						|
			compatible = "corp,bar";
 | 
						|
			... /* various properties and child nodes */
 | 
						|
		};
 | 
						|
	};
 | 
						|
    ---- bar.dts ---------------------------------------------------------------
 | 
						|
 | 
						|
when loaded (and resolved as described in [1]) should result in foo+bar.dts::
 | 
						|
 | 
						|
    ---- foo+bar.dts -----------------------------------------------------------
 | 
						|
	/* FOO platform + bar peripheral */
 | 
						|
	/ {
 | 
						|
		compatible = "corp,foo";
 | 
						|
 | 
						|
		/* shared resources */
 | 
						|
		res: res {
 | 
						|
		};
 | 
						|
 | 
						|
		/* On chip peripherals */
 | 
						|
		ocp: ocp {
 | 
						|
			/* peripherals that are always instantiated */
 | 
						|
			peripheral1 { ... };
 | 
						|
 | 
						|
			/* bar peripheral */
 | 
						|
			bar {
 | 
						|
				compatible = "corp,bar";
 | 
						|
				... /* various properties and child nodes */
 | 
						|
			};
 | 
						|
		};
 | 
						|
	};
 | 
						|
    ---- foo+bar.dts -----------------------------------------------------------
 | 
						|
 | 
						|
As a result of the overlay, a new device node (bar) has been created
 | 
						|
so a bar platform device will be registered and if a matching device driver
 | 
						|
is loaded the device will be created as expected.
 | 
						|
 | 
						|
If the base DT was not compiled with the -@ option then the "&ocp" label
 | 
						|
will not be available to resolve the overlay node(s) to the proper location
 | 
						|
in the base DT. In this case, the target path can be provided. The target
 | 
						|
location by label syntax is preferred because the overlay can be applied to
 | 
						|
any base DT containing the label, no matter where the label occurs in the DT.
 | 
						|
 | 
						|
The above bar.dts example modified to use target path syntax is::
 | 
						|
 | 
						|
    ---- bar.dts - overlay target location by explicit path --------------------
 | 
						|
	/dts-v1/;
 | 
						|
	/plugin/;
 | 
						|
	&{/ocp} {
 | 
						|
		/* bar peripheral */
 | 
						|
		bar {
 | 
						|
			compatible = "corp,bar";
 | 
						|
			... /* various properties and child nodes */
 | 
						|
		}
 | 
						|
	};
 | 
						|
    ---- bar.dts ---------------------------------------------------------------
 | 
						|
 | 
						|
 | 
						|
Overlay in-kernel API
 | 
						|
--------------------------------
 | 
						|
 | 
						|
The API is quite easy to use.
 | 
						|
 | 
						|
1) Call of_overlay_fdt_apply() to create and apply an overlay changeset. The
 | 
						|
   return value is an error or a cookie identifying this overlay.
 | 
						|
 | 
						|
2) Call of_overlay_remove() to remove and cleanup the overlay changeset
 | 
						|
   previously created via the call to of_overlay_fdt_apply(). Removal of an
 | 
						|
   overlay changeset that is stacked by another will not be permitted.
 | 
						|
 | 
						|
Finally, if you need to remove all overlays in one-go, just call
 | 
						|
of_overlay_remove_all() which will remove every single one in the correct
 | 
						|
order.
 | 
						|
 | 
						|
There is the option to register notifiers that get called on
 | 
						|
overlay operations. See of_overlay_notifier_register/unregister and
 | 
						|
enum of_overlay_notify_action for details.
 | 
						|
 | 
						|
A notifier callback for OF_OVERLAY_PRE_APPLY, OF_OVERLAY_POST_APPLY, or
 | 
						|
OF_OVERLAY_PRE_REMOVE may store pointers to a device tree node in the overlay
 | 
						|
or its content but these pointers must not persist past the notifier callback
 | 
						|
for OF_OVERLAY_POST_REMOVE.  The memory containing the overlay will be
 | 
						|
kfree()ed after OF_OVERLAY_POST_REMOVE notifiers are called.  Note that the
 | 
						|
memory will be kfree()ed even if the notifier for OF_OVERLAY_POST_REMOVE
 | 
						|
returns an error.
 | 
						|
 | 
						|
The changeset notifiers in drivers/of/dynamic.c are a second type of notifier
 | 
						|
that could be triggered by applying or removing an overlay.  These notifiers
 | 
						|
are not allowed to store pointers to a device tree node in the overlay
 | 
						|
or its content.  The overlay code does not protect against such pointers
 | 
						|
remaining active when the memory containing the overlay is freed as a result
 | 
						|
of removing the overlay.
 | 
						|
 | 
						|
Any other code that retains a pointer to the overlay nodes or data is
 | 
						|
considered to be a bug because after removing the overlay the pointer
 | 
						|
will refer to freed memory.
 | 
						|
 | 
						|
Users of overlays must be especially aware of the overall operations that
 | 
						|
occur on the system to ensure that other kernel code does not retain any
 | 
						|
pointers to the overlay nodes or data.  Any example of an inadvertent use
 | 
						|
of such pointers is if a driver or subsystem module is loaded after an
 | 
						|
overlay has been applied, and the driver or subsystem scans the entire
 | 
						|
devicetree or a large portion of it, including the overlay nodes.
 |