162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci.. include:: ../disclaimer-zh_CN.rst
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci:Original: Documentation/devicetree/overlay-notes.rst
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci:翻译:
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci 司延腾 Yanteng Si <siyanteng@loongson.cn>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci:校译:
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci==============
1362306a36Sopenharmony_ci设备树覆盖说明
1462306a36Sopenharmony_ci==============
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci本文档描述了drivers/of/overlay.c中的内核内设备树覆盖功能的实现,是
1762306a36Sopenharmony_ciDocumentation/devicetree/dynamic-resolution-notes.rst[1]的配套文档。
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci覆盖如何工作
2062306a36Sopenharmony_ci------------
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci设备树覆盖的目的是修改内核的实时树,并使修改以反映变化的方式影响内核的状态。
2362306a36Sopenharmony_ci由于内核主要处理的是设备,任何新的设备节点如果导致一个活动的设备,就应该创建它,
2462306a36Sopenharmony_ci而如果设备节点被禁用或被全部删除,受影响的设备应该被取消注册。
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci让我们举个例子,我们有一个foo板,它的基本树形图如下::
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci    ---- foo.dts ---------------------------------------------------------------
2962306a36Sopenharmony_ci	/* FOO平台 */
3062306a36Sopenharmony_ci	/dts-v1/;
3162306a36Sopenharmony_ci	/ {
3262306a36Sopenharmony_ci		compatible = "corp,foo";
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci		/* 共享的资源 */
3562306a36Sopenharmony_ci		res: res {
3662306a36Sopenharmony_ci		};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci		/* 芯片上的外围设备 */
3962306a36Sopenharmony_ci		ocp: ocp {
4062306a36Sopenharmony_ci			/* 总是被实例化的外围设备 */
4162306a36Sopenharmony_ci			peripheral1 { ... };
4262306a36Sopenharmony_ci		};
4362306a36Sopenharmony_ci	};
4462306a36Sopenharmony_ci    ---- foo.dts ---------------------------------------------------------------
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci覆盖bar.dts,
4762306a36Sopenharmony_ci::
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci    ---- bar.dts - 按标签覆盖目标位置 ----------------------------
5062306a36Sopenharmony_ci	/dts-v1/;
5162306a36Sopenharmony_ci	/插件/;
5262306a36Sopenharmony_ci	&ocp {
5362306a36Sopenharmony_ci		/* bar外围 */
5462306a36Sopenharmony_ci		bar {
5562306a36Sopenharmony_ci			compatible = "corp,bar";
5662306a36Sopenharmony_ci			... /* 各种属性和子节点 */
5762306a36Sopenharmony_ci		};
5862306a36Sopenharmony_ci	};
5962306a36Sopenharmony_ci    ---- bar.dts ---------------------------------------------------------------
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci当加载(并按照[1]中描述的方式解决)时,应该产生foo+bar.dts::
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci    ---- foo+bar.dts -----------------------------------------------------------
6462306a36Sopenharmony_ci	/* FOO平台 + bar外围 */
6562306a36Sopenharmony_ci	/ {
6662306a36Sopenharmony_ci		compatible = "corp,foo";
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		/* 共享资源 */
6962306a36Sopenharmony_ci		res: res {
7062306a36Sopenharmony_ci		};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci		/* 芯片上的外围设备 */
7362306a36Sopenharmony_ci		ocp: ocp {
7462306a36Sopenharmony_ci			/* 总是被实例化的外围设备 */
7562306a36Sopenharmony_ci			peripheral1 { ... };
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci			/* bar外围 */
7862306a36Sopenharmony_ci			bar {
7962306a36Sopenharmony_ci				compatible = "corp,bar";
8062306a36Sopenharmony_ci				... /* 各种属性和子节点 */
8162306a36Sopenharmony_ci			};
8262306a36Sopenharmony_ci		};
8362306a36Sopenharmony_ci	};
8462306a36Sopenharmony_ci    ---- foo+bar.dts -----------------------------------------------------------
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci作为覆盖的结果,已经创建了一个新的设备节点(bar),因此将注册一个bar平台设备,
8762306a36Sopenharmony_ci如果加载了匹配的设备驱动程序,将按预期创建设备。
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci如果基础DT不是用-@选项编译的,那么“&ocp”标签将不能用于将覆盖节点解析到基础
9062306a36Sopenharmony_ciDT中的适当位置。在这种情况下,可以提供目标路径。通过标签的目标位置的语法是比
9162306a36Sopenharmony_ci较好的,因为不管标签在DT中出现在哪里,覆盖都可以被应用到任何包含标签的基础DT上。
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci上面的bar.dts例子被修改为使用目标路径语法,即为::
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci    ---- bar.dts - 通过明确的路径覆盖目标位置 --------------------
9662306a36Sopenharmony_ci	/dts-v1/;
9762306a36Sopenharmony_ci	/插件/;
9862306a36Sopenharmony_ci	&{/ocp} {
9962306a36Sopenharmony_ci		/* bar外围 */
10062306a36Sopenharmony_ci		bar {
10162306a36Sopenharmony_ci			compatible = "corp,bar";
10262306a36Sopenharmony_ci			... /* 各种外围设备和子节点 */
10362306a36Sopenharmony_ci		}
10462306a36Sopenharmony_ci	};
10562306a36Sopenharmony_ci    ---- bar.dts ---------------------------------------------------------------
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci内核中关于覆盖的API
10962306a36Sopenharmony_ci-------------------
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci该API相当容易使用。
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci1) 调用of_overlay_fdt_apply()来创建和应用一个覆盖的变更集。返回值是一个
11462306a36Sopenharmony_ci   错误或一个识别这个覆盖的cookie。
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci2) 调用of_overlay_remove()来删除和清理先前通过调用of_overlay_fdt_apply()
11762306a36Sopenharmony_ci   而创建的覆盖变更集。不允许删除一个被另一个覆盖的覆盖变化集。
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci最后,如果你需要一次性删除所有的覆盖,只需调用of_overlay_remove_all(),
12062306a36Sopenharmony_ci它将以正确的顺序删除每一个覆盖。
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci你可以选择注册在覆盖操作中被调用的通知器。详见
12362306a36Sopenharmony_ciof_overlay_notifier_register/unregister和enum of_overlay_notify_action。
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ciOF_OVERLAY_PRE_APPLY、OF_OVERLAY_POST_APPLY或OF_OVERLAY_PRE_REMOVE
12662306a36Sopenharmony_ci的通知器回调可以存储指向覆盖层中的设备树节点或其内容的指针,但这些指针不能持
12762306a36Sopenharmony_ci续到OF_OVERLAY_POST_REMOVE的通知器回调。在OF_OVERLAY_POST_REMOVE通
12862306a36Sopenharmony_ci知器被调用后,包含覆盖层的内存将被kfree()ed。请注意,即使OF_OVERLAY_POST_REMOVE
12962306a36Sopenharmony_ci的通知器返回错误,内存也会被kfree()ed。
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cidrivers/of/dynamic.c中的变更集通知器是第二种类型的通知器,可以通过应用或移除
13262306a36Sopenharmony_ci覆盖层来触发。这些通知器不允许在覆盖层或其内容中存储指向设备树节点的指针。当包含
13362306a36Sopenharmony_ci覆盖层的内存因移除覆盖层而被释放时,覆盖层代码并不能防止这类指针仍然有效。
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci任何其他保留指向覆盖层节点或数据的指针的代码都被认为是一个错误,因为在移除覆盖层
13662306a36Sopenharmony_ci后,该指针将指向已释放的内存。
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci覆盖层的用户必须特别注意系统上发生的整体操作,以确保其他内核代码不保留任何指向覆
13962306a36Sopenharmony_ci盖层节点或数据的指针。任何无意中使用这种指针的例子是,如果一个驱动或子系统模块在
14062306a36Sopenharmony_ci应用了覆盖后被加载,并且该驱动或子系统扫描了整个设备树或其大部分,包括覆盖节点。
141