xref: /OK3568_Linux_fs/yocto/poky/meta/classes/devicetree.bbclass (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# This bbclass implements device tree compliation for user provided device tree
2*4882a593Smuzhiyun# sources. The compilation of the device tree sources is the same as the kernel
3*4882a593Smuzhiyun# device tree compilation process, this includes being able to include sources
4*4882a593Smuzhiyun# from the kernel such as soc dtsi files or header files such as gpio.h. In
5*4882a593Smuzhiyun# addition to device trees this bbclass also handles compilation of device tree
6*4882a593Smuzhiyun# overlays.
7*4882a593Smuzhiyun#
8*4882a593Smuzhiyun# The output of this class behaves similar to how kernel-devicetree.bbclass
9*4882a593Smuzhiyun# operates in that the output files are installed into /boot/devicetree.
10*4882a593Smuzhiyun# However this class on purpose separates the deployed device trees into the
11*4882a593Smuzhiyun# 'devicetree' subdirectory. This prevents clashes with the kernel-devicetree
12*4882a593Smuzhiyun# output. Additionally the device trees are populated into the sysroot for
13*4882a593Smuzhiyun# access via the sysroot from within other recipes.
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunSECTION ?= "bsp"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun# The default inclusion of kernel device tree includes and headers means that
18*4882a593Smuzhiyun# device trees built with them are at least GPL-2.0-only (and in some cases dual
19*4882a593Smuzhiyun# licensed). Default to GPL-2.0-only if the recipe does not specify a license.
20*4882a593SmuzhiyunLICENSE ?= "GPL-2.0-only"
21*4882a593SmuzhiyunLIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6"
22*4882a593Smuzhiyun
23*4882a593SmuzhiyunINHIBIT_DEFAULT_DEPS = "1"
24*4882a593SmuzhiyunDEPENDS += "dtc-native"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyuninherit deploy kernel-arch
27*4882a593Smuzhiyun
28*4882a593SmuzhiyunCOMPATIBLE_MACHINE ?= "^$"
29*4882a593Smuzhiyun
30*4882a593SmuzhiyunPROVIDES = "virtual/dtb"
31*4882a593Smuzhiyun
32*4882a593SmuzhiyunPACKAGE_ARCH = "${MACHINE_ARCH}"
33*4882a593Smuzhiyun
34*4882a593SmuzhiyunSYSROOT_DIRS += "/boot/devicetree"
35*4882a593SmuzhiyunFILES:${PN} = "/boot/devicetree/*.dtb /boot/devicetree/*.dtbo"
36*4882a593Smuzhiyun
37*4882a593SmuzhiyunS = "${WORKDIR}"
38*4882a593SmuzhiyunB = "${WORKDIR}/build"
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun# Default kernel includes, these represent what are normally used for in-kernel
41*4882a593Smuzhiyun# sources.
42*4882a593SmuzhiyunKERNEL_INCLUDE ??= " \
43*4882a593Smuzhiyun        ${STAGING_KERNEL_DIR}/arch/${ARCH}/boot/dts \
44*4882a593Smuzhiyun        ${STAGING_KERNEL_DIR}/arch/${ARCH}/boot/dts/* \
45*4882a593Smuzhiyun        ${STAGING_KERNEL_DIR}/scripts/dtc/include-prefixes \
46*4882a593Smuzhiyun        "
47*4882a593Smuzhiyun
48*4882a593SmuzhiyunDT_INCLUDE[doc] = "Search paths to be made available to both the device tree compiler and preprocessor for inclusion."
49*4882a593SmuzhiyunDT_INCLUDE ?= "${DT_FILES_PATH} ${KERNEL_INCLUDE}"
50*4882a593SmuzhiyunDT_FILES_PATH[doc] = "Defaults to source directory, can be used to select dts files that are not in source (e.g. generated)."
51*4882a593SmuzhiyunDT_FILES_PATH ?= "${S}"
52*4882a593Smuzhiyun
53*4882a593SmuzhiyunDT_PADDING_SIZE[doc] = "Size of padding on the device tree blob, used as extra space typically for additional properties during boot."
54*4882a593SmuzhiyunDT_PADDING_SIZE ??= "0x3000"
55*4882a593SmuzhiyunDT_RESERVED_MAP[doc] = "Number of reserved map entires."
56*4882a593SmuzhiyunDT_RESERVED_MAP ??= "8"
57*4882a593SmuzhiyunDT_BOOT_CPU[doc] = "The boot cpu, defaults to 0"
58*4882a593SmuzhiyunDT_BOOT_CPU ??= "0"
59*4882a593Smuzhiyun
60*4882a593SmuzhiyunDTC_FLAGS ?= "-R ${DT_RESERVED_MAP} -b ${DT_BOOT_CPU}"
61*4882a593SmuzhiyunDTC_PPFLAGS ?= "-nostdinc -undef -D__DTS__ -x assembler-with-cpp"
62*4882a593SmuzhiyunDTC_BFLAGS ?= "-p ${DT_PADDING_SIZE} -@"
63*4882a593SmuzhiyunDTC_OFLAGS ?= "-p 0 -@ -H epapr"
64*4882a593Smuzhiyun
65*4882a593Smuzhiyunpython () {
66*4882a593Smuzhiyun    if d.getVar("KERNEL_INCLUDE"):
67*4882a593Smuzhiyun        # auto add dependency on kernel tree, but only if kernel include paths
68*4882a593Smuzhiyun        # are specified.
69*4882a593Smuzhiyun        d.appendVarFlag("do_compile", "depends", " virtual/kernel:do_configure")
70*4882a593Smuzhiyun}
71*4882a593Smuzhiyun
72*4882a593Smuzhiyundef expand_includes(varname, d):
73*4882a593Smuzhiyun    import glob
74*4882a593Smuzhiyun    includes = set()
75*4882a593Smuzhiyun    # expand all includes with glob
76*4882a593Smuzhiyun    for i in (d.getVar(varname) or "").split():
77*4882a593Smuzhiyun        for g in glob.glob(i):
78*4882a593Smuzhiyun            if os.path.isdir(g): # only add directories to include path
79*4882a593Smuzhiyun                includes.add(g)
80*4882a593Smuzhiyun    return includes
81*4882a593Smuzhiyun
82*4882a593Smuzhiyundef devicetree_source_is_overlay(path):
83*4882a593Smuzhiyun    # determine if a dts file is an overlay by checking if it uses "/plugin/;"
84*4882a593Smuzhiyun    with open(path, "r") as f:
85*4882a593Smuzhiyun        for i in f:
86*4882a593Smuzhiyun            if i.startswith("/plugin/;"):
87*4882a593Smuzhiyun                return True
88*4882a593Smuzhiyun    return False
89*4882a593Smuzhiyun
90*4882a593Smuzhiyundef devicetree_compile(dtspath, includes, d):
91*4882a593Smuzhiyun    import subprocess
92*4882a593Smuzhiyun    dts = os.path.basename(dtspath)
93*4882a593Smuzhiyun    dtname = os.path.splitext(dts)[0]
94*4882a593Smuzhiyun    bb.note("Processing {0} [{1}]".format(dtname, dts))
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun    # preprocess
97*4882a593Smuzhiyun    ppargs = d.getVar("BUILD_CPP").split()
98*4882a593Smuzhiyun    ppargs += (d.getVar("DTC_PPFLAGS") or "").split()
99*4882a593Smuzhiyun    for i in includes:
100*4882a593Smuzhiyun        ppargs.append("-I{0}".format(i))
101*4882a593Smuzhiyun    ppargs += ["-o", "{0}.pp".format(dts), dtspath]
102*4882a593Smuzhiyun    bb.note("Running {0}".format(" ".join(ppargs)))
103*4882a593Smuzhiyun    subprocess.run(ppargs, check = True)
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun    # determine if the file is an overlay or not (using the preprocessed file)
106*4882a593Smuzhiyun    isoverlay = devicetree_source_is_overlay("{0}.pp".format(dts))
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun    # compile
109*4882a593Smuzhiyun    dtcargs = ["dtc"] + (d.getVar("DTC_FLAGS") or "").split()
110*4882a593Smuzhiyun    if isoverlay:
111*4882a593Smuzhiyun        dtcargs += (d.getVar("DTC_OFLAGS") or "").split()
112*4882a593Smuzhiyun    else:
113*4882a593Smuzhiyun        dtcargs += (d.getVar("DTC_BFLAGS") or "").split()
114*4882a593Smuzhiyun    for i in includes:
115*4882a593Smuzhiyun        dtcargs += ["-i", i]
116*4882a593Smuzhiyun    dtcargs += ["-o", "{0}.{1}".format(dtname, "dtbo" if isoverlay else "dtb")]
117*4882a593Smuzhiyun    dtcargs += ["-I", "dts", "-O", "dtb", "{0}.pp".format(dts)]
118*4882a593Smuzhiyun    bb.note("Running {0}".format(" ".join(dtcargs)))
119*4882a593Smuzhiyun    subprocess.run(dtcargs, check = True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
120*4882a593Smuzhiyun
121*4882a593Smuzhiyunpython devicetree_do_compile() {
122*4882a593Smuzhiyun    includes = expand_includes("DT_INCLUDE", d)
123*4882a593Smuzhiyun    listpath = d.getVar("DT_FILES_PATH")
124*4882a593Smuzhiyun    for dts in os.listdir(listpath):
125*4882a593Smuzhiyun        dtspath = os.path.join(listpath, dts)
126*4882a593Smuzhiyun        try:
127*4882a593Smuzhiyun            if not(os.path.isfile(dtspath)) or not(dts.endswith(".dts") or devicetree_source_is_overlay(dtspath)):
128*4882a593Smuzhiyun                continue # skip non-.dts files and non-overlay files
129*4882a593Smuzhiyun        except:
130*4882a593Smuzhiyun            continue # skip if can't determine if overlay
131*4882a593Smuzhiyun        devicetree_compile(dtspath, includes, d)
132*4882a593Smuzhiyun}
133*4882a593Smuzhiyun
134*4882a593Smuzhiyundevicetree_do_install() {
135*4882a593Smuzhiyun    for DTB_FILE in `ls *.dtb *.dtbo`; do
136*4882a593Smuzhiyun        install -Dm 0644 ${B}/${DTB_FILE} ${D}/boot/devicetree/${DTB_FILE}
137*4882a593Smuzhiyun    done
138*4882a593Smuzhiyun}
139*4882a593Smuzhiyun
140*4882a593Smuzhiyundevicetree_do_deploy() {
141*4882a593Smuzhiyun    for DTB_FILE in `ls *.dtb *.dtbo`; do
142*4882a593Smuzhiyun        install -Dm 0644 ${B}/${DTB_FILE} ${DEPLOYDIR}/devicetree/${DTB_FILE}
143*4882a593Smuzhiyun    done
144*4882a593Smuzhiyun}
145*4882a593Smuzhiyunaddtask deploy before do_build after do_install
146*4882a593Smuzhiyun
147*4882a593SmuzhiyunEXPORT_FUNCTIONS do_compile do_install do_deploy
148*4882a593Smuzhiyun
149