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